vortex_buffer/
alignment.rs1use std::fmt::Display;
5use std::ops::Deref;
6
7use vortex_error::VortexExpect;
8
9#[derive(Clone, Debug, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
14pub struct Alignment(usize);
15
16impl Alignment {
17 #[inline]
23 pub const fn new(align: usize) -> Self {
24 assert!(align > 0, "Alignment must be greater than 0");
25 assert!(align <= u16::MAX as usize, "Alignment must fit into u16");
26 assert!(align.is_power_of_two(), "Alignment must be a power of 2");
27 Self(align)
28 }
29
30 #[inline]
32 pub const fn none() -> Self {
33 Self::new(1)
34 }
35
36 #[inline]
48 pub const fn of<T>() -> Self {
49 Self::new(align_of::<T>())
50 }
51
52 #[inline]
65 pub fn is_aligned_to(&self, other: Alignment) -> bool {
66 self.0.trailing_zeros() >= other.0.trailing_zeros()
69 }
70
71 pub fn exponent(&self) -> u8 {
73 u8::try_from(self.0.trailing_zeros())
74 .vortex_expect("alignment fits into u16, so exponent fits in u7")
75 }
76
77 #[inline]
83 pub const fn from_exponent(exponent: u8) -> Self {
84 Self::new(1 << exponent)
85 }
86}
87
88impl Display for Alignment {
89 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
90 write!(f, "{}", self.0)
91 }
92}
93
94impl Deref for Alignment {
95 type Target = usize;
96
97 #[inline]
98 fn deref(&self) -> &Self::Target {
99 &self.0
100 }
101}
102
103impl From<usize> for Alignment {
104 #[inline]
105 fn from(value: usize) -> Self {
106 Self::new(value)
107 }
108}
109
110impl From<u16> for Alignment {
111 #[inline]
112 fn from(value: u16) -> Self {
113 Self::new(usize::from(value))
114 }
115}
116
117impl From<Alignment> for usize {
118 #[inline]
119 fn from(value: Alignment) -> Self {
120 value.0
121 }
122}
123
124impl From<Alignment> for u16 {
125 #[inline]
126 fn from(value: Alignment) -> Self {
127 u16::try_from(value.0).vortex_expect("Alignment must fit into u16")
128 }
129}
130
131#[cfg(test)]
132mod test {
133 use super::*;
134
135 #[test]
136 #[should_panic]
137 fn alignment_zero() {
138 Alignment::new(0);
139 }
140
141 #[test]
142 #[should_panic]
143 fn alignment_overflow() {
144 Alignment::new(u16::MAX as usize + 1);
145 }
146
147 #[test]
148 #[should_panic]
149 fn alignment_not_power_of_two() {
150 Alignment::new(3);
151 }
152
153 #[test]
154 fn alignment_exponent() {
155 let alignment = Alignment::new(1024);
156 assert_eq!(alignment.exponent(), 10);
157 assert_eq!(Alignment::from_exponent(10), alignment);
158 }
159
160 #[test]
161 fn is_aligned_to() {
162 assert!(Alignment::new(1).is_aligned_to(Alignment::new(1)));
163 assert!(Alignment::new(2).is_aligned_to(Alignment::new(1)));
164 assert!(Alignment::new(4).is_aligned_to(Alignment::new(1)));
165 assert!(!Alignment::new(1).is_aligned_to(Alignment::new(2)));
166 }
167}