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 pub const fn none() -> Self {
32 Self::new(1)
33 }
34
35 #[inline]
47 pub const fn of<T>() -> Self {
48 Self::new(align_of::<T>())
49 }
50
51 #[inline]
64 pub fn is_aligned_to(&self, other: Alignment) -> bool {
65 self.0.trailing_zeros() >= other.0.trailing_zeros()
68 }
69
70 pub fn exponent(&self) -> u8 {
72 u8::try_from(self.0.trailing_zeros())
73 .vortex_expect("alignment fits into u16, so exponent fits in u7")
74 }
75
76 #[inline]
82 pub const fn from_exponent(exponent: u8) -> Self {
83 Self::new(1 << exponent)
84 }
85}
86
87impl Display for Alignment {
88 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
89 write!(f, "{}", self.0)
90 }
91}
92
93impl Deref for Alignment {
94 type Target = usize;
95
96 fn deref(&self) -> &Self::Target {
97 &self.0
98 }
99}
100
101impl From<usize> for Alignment {
102 fn from(value: usize) -> Self {
103 Self::new(value)
104 }
105}
106
107impl From<u16> for Alignment {
108 fn from(value: u16) -> Self {
109 Self::new(usize::from(value))
110 }
111}
112
113impl From<Alignment> for usize {
114 fn from(value: Alignment) -> Self {
115 value.0
116 }
117}
118
119impl From<Alignment> for u16 {
120 fn from(value: Alignment) -> Self {
121 u16::try_from(value.0).vortex_expect("Alignment must fit into u16")
122 }
123}
124
125#[cfg(test)]
126mod test {
127 use super::*;
128
129 #[test]
130 #[should_panic]
131 fn alignment_zero() {
132 Alignment::new(0);
133 }
134
135 #[test]
136 #[should_panic]
137 fn alignment_overflow() {
138 Alignment::new(u16::MAX as usize + 1);
139 }
140
141 #[test]
142 #[should_panic]
143 fn alignment_not_power_of_two() {
144 Alignment::new(3);
145 }
146
147 #[test]
148 fn alignment_exponent() {
149 let alignment = Alignment::new(1024);
150 assert_eq!(alignment.exponent(), 10);
151 assert_eq!(Alignment::from_exponent(10), alignment);
152 }
153
154 #[test]
155 fn is_aligned_to() {
156 assert!(Alignment::new(1).is_aligned_to(Alignment::new(1)));
157 assert!(Alignment::new(2).is_aligned_to(Alignment::new(1)));
158 assert!(Alignment::new(4).is_aligned_to(Alignment::new(1)));
159 assert!(!Alignment::new(1).is_aligned_to(Alignment::new(2)));
160 }
161}