Skip to main content

num_align/
lib.rs

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}