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