1pub const MIN_ALIGN: usize = 8;
11
12pub fn needs_padding(align: usize) -> bool {
14 align > MIN_ALIGN
15}
16
17pub fn padded_size(size: usize, align: usize) -> Option<usize> {
20 size.checked_add(align)
21}
22
23pub fn offset(raw: usize, align: usize) -> usize {
30 align - raw % align
31}
32
33#[cfg(test)]
34mod tests {
35 use super::*;
36
37 #[test]
38 fn only_alignments_above_the_sdks_are_padded() {
39 assert!(!needs_padding(1));
40 assert!(!needs_padding(MIN_ALIGN));
41 assert!(needs_padding(16));
42 }
43
44 #[test]
45 fn the_padded_size_adds_the_alignment() {
46 assert_eq!(padded_size(100, 16), Some(116));
47 assert_eq!(padded_size(usize::MAX, 16), None);
48 }
49
50 #[test]
51 fn the_pointer_is_aligned_inside_the_block_with_room_for_an_address() {
52 for align in [16, 32, 64, 4096] {
53 for raw in (0..2 * align).step_by(MIN_ALIGN).map(|r| 0x2000_0000 + r) {
54 let at = offset(raw, align);
55 assert_eq!((raw + at) % align, 0, "raw {raw:#x} align {align}");
56 assert!(at >= MIN_ALIGN && at >= size_of::<usize>(), "{at}");
57 assert!(at <= align, "{at}");
58 }
59 }
60 }
61
62 #[test]
63 fn an_already_aligned_block_still_moves_a_whole_alignment() {
64 assert_eq!(offset(0x1000, 16), 16);
65 assert_eq!(offset(0x1008, 16), 8);
66 }
67}