pelite\util/
align.rs

1
2/// Helper to implement generic alignment operator.
3pub trait AlignTo {
4	type TAlign;
5	/// Aligns the given value to a multiple of the align value.
6	///
7	/// Debug asserts that align is a power of two, otherwise calculates an incorrect result.
8	fn align_to(self, align: Self::TAlign) -> Self;
9	/// Checks if the given value is aligned to a multiple of the align value.
10	///
11	/// Debug asserts that align is a power of two, otherwise calculates an incorrect result.
12	fn aligned_to(self, align: Self::TAlign) -> bool;
13}
14
15macro_rules! impl_align_to {
16	($ty:ty) => {
17		impl AlignTo for $ty {
18			type TAlign = $ty;
19			#[inline(always)]
20			fn align_to(self, align: $ty) -> $ty {
21				debug_assert!(align.is_power_of_two(), "align ({:#x}) is not a power of two", align);
22				let mask = align - 1;
23				self.wrapping_add(mask) & !mask
24			}
25			#[inline(always)]
26			fn aligned_to(self, align: $ty) -> bool {
27				debug_assert!(align.is_power_of_two(), "align ({:#x}) is not a power of two", align);
28				let mask = align - 1;
29				self & mask == 0
30			}
31		}
32	};
33}
34impl_align_to!(u8);
35impl_align_to!(u16);
36impl_align_to!(u32);
37impl_align_to!(u64);
38impl_align_to!(u128);
39impl_align_to!(usize);
40
41impl<T> AlignTo for *const T {
42	type TAlign = usize;
43	#[inline(always)]
44	fn align_to(self, align: usize) -> *const T {
45		(self as usize).align_to(align) as *const T
46	}
47	#[inline(always)]
48	fn aligned_to(self, align: usize) -> bool {
49		(self as usize).aligned_to(align)
50	}
51}
52
53impl<T> AlignTo for *mut T {
54	type TAlign = usize;
55	#[inline(always)]
56	fn align_to(self, align: usize) -> *mut T {
57		(self as usize).align_to(align) as *mut T
58	}
59	#[inline(always)]
60	fn aligned_to(self, align: usize) -> bool {
61		(self as usize).aligned_to(align)
62	}
63}
64
65#[test]
66fn test_align_to() {
67	assert_eq!(0, 0_u32.align_to(256_u32));
68	assert_eq!(0, (!0_u32).align_to(256_u32));
69	assert_eq!(128, 65_u32.align_to(64_u32));
70	assert_eq!(64, 64_u32.align_to(64_u32));
71}