1#![cfg_attr(not(test), no_std)]
2
3pub trait NumAlign {
4 fn align_up(self, align: usize) -> Self;
5 fn align_down(self, align: usize) -> Self;
6}
7pub trait NumAssertAlign: Copy {
8 fn is_aligned_to(self, align: usize) -> bool;
9}
10
11macro_rules! impl_num_align {
12 ($t:ty) => {
13 impl NumAlign for $t {
14 #[inline(always)]
15 fn align_up(self, align: usize) -> Self {
16 if self.is_aligned_to(align) {
17 self
18 } else {
19 (self as usize + align - self as usize % align) as _
20 }
21 }
22
23 #[inline(always)]
24 fn align_down(self, align: usize) -> Self {
25 if self.is_aligned_to(align) {
26 self
27 } else {
28 (self as usize - self as usize % align) as _
29 }
30 }
31 }
32 impl NumAssertAlign for $t {
33 #[inline(always)]
34 fn is_aligned_to(self, align: usize) -> bool {
35 self as usize % align == 0
36 }
37 }
38 };
39}
40
41impl_num_align!(usize);
42impl_num_align!(u64);
43impl_num_align!(u32);
44
45impl<T> NumAlign for *const T {
46 #[inline(always)]
47 fn align_up(self, align: usize) -> Self {
48 (self as usize).align_up(align) as _
49 }
50
51 #[inline(always)]
52 fn align_down(self, align: usize) -> Self {
53 (self as usize).align_down(align) as _
54 }
55}
56
57impl<T> NumAlign for *mut T {
58 #[inline(always)]
59 fn align_up(self, align: usize) -> Self {
60 (self as usize).align_up(align) as _
61 }
62
63 #[inline(always)]
64 fn align_down(self, align: usize) -> Self {
65 (self as usize).align_down(align) as _
66 }
67}
68
69#[cfg(test)]
70mod tests {
71 use super::*;
72
73 #[test]
74 fn test_align() {
75 assert_eq!(0x1000usize.align_up(0x1000), 0x1000);
76 assert_eq!(0x1000usize.align_down(0x1000), 0x1000);
77 assert_eq!(0x1001usize.align_up(0x1000), 0x2000);
78 assert_eq!(0x1001usize.align_down(0x1000), 0x1000);
79 assert!(0x1000usize.is_aligned_to(0x1000));
80 assert!(!0x1001usize.is_aligned_to(0x1000));
81 }
82
83 #[test]
84 fn test_align2() {
85 assert_eq!((0x1000 as *const u8).align_up(0x1000), 0x1000 as *const u8);
86
87 assert_eq!(
88 (0x1000 as *const u8).align_down(0x1000),
89 0x1000 as *const u8
90 );
91
92 assert_eq!((0x1001 as *const u8).align_up(0x1000), 0x2000 as *const u8);
93
94 assert_eq!(
95 (0x1001 as *const u8).align_down(0x1000),
96 0x1000 as *const u8
97 );
98 }
99}