Skip to main content

osom_lib_primitives/
align.rs

1//! Holds the [`Align`] primitive.
2
3#![allow(clippy::unreadable_literal)]
4
5use paste::paste;
6
7use osom_lib_reprc::{macros::reprc, traits::ReprC};
8
9/// Represents a zero-sized type that has `ALIGN` as its alignment.
10/// By embedding it into a struct we can enforce a different alignment
11/// based on `const ALIGN: usize` generic parameter.
12///
13/// # Example
14///
15/// ```rust
16/// use osom_lib_primitives::align::{Align, Alignment};
17///
18/// /// This struct's alignment depends on `ALIGN` parameter.
19/// pub struct TestAlign<const ALIGN: usize>
20/// where
21///     Align<ALIGN>: Alignment,
22/// {
23///     _inner: Align<ALIGN>,
24/// }
25/// ```
26#[reprc]
27#[repr(transparent)]
28#[derive(Debug, Default, PartialEq, Eq, Clone, Copy)]
29#[must_use]
30pub struct Align<const ALIGN: usize>
31where
32    Self: Alignment,
33{
34    inner: [<Self as private::AlignedTrait>::AlignedType; 0],
35}
36
37impl<const ALIGN: usize> Align<ALIGN>
38where
39    Self: Alignment,
40{
41    #[inline(always)]
42    pub const fn default() -> Self {
43        Self { inner: [] }
44    }
45}
46
47/// A helper trait to put for constrainting generic `ALIGN` parameter.
48pub trait Alignment: private::AlignedTrait {}
49
50#[allow(clippy::wildcard_imports)]
51mod private {
52    use super::*;
53
54    pub trait AlignedTrait {
55        /// A zero-sized type of particular alignment.
56        type AlignedType: core::fmt::Debug + Copy + Eq + PartialEq + Send + Sync + Unpin + ReprC;
57    }
58
59    macro_rules! align_impl {
60        ( $size: literal ) => {
61            paste! {
62                #[reprc]
63                #[repr(C, align($size))]
64                #[derive(Debug, Default, PartialEq, Eq, Clone, Copy)]
65                pub struct [< Align $size >] { }
66
67                impl AlignedTrait for Align<$size> {
68                    type AlignedType = [< Align $size >];
69                }
70
71                impl Alignment for Align<$size> { }
72            }
73        };
74    }
75
76    align_impl!(0b00000000_00000000_00000000_00000001);
77    align_impl!(0b00000000_00000000_00000000_00000010);
78    align_impl!(0b00000000_00000000_00000000_00000100);
79    align_impl!(0b00000000_00000000_00000000_00001000);
80    align_impl!(0b00000000_00000000_00000000_00010000);
81    align_impl!(0b00000000_00000000_00000000_00100000);
82    align_impl!(0b00000000_00000000_00000000_01000000);
83    align_impl!(0b00000000_00000000_00000000_10000000);
84    align_impl!(0b00000000_00000000_00000001_00000000);
85    align_impl!(0b00000000_00000000_00000010_00000000);
86    align_impl!(0b00000000_00000000_00000100_00000000);
87    align_impl!(0b00000000_00000000_00001000_00000000);
88    align_impl!(0b00000000_00000000_00010000_00000000);
89    align_impl!(0b00000000_00000000_00100000_00000000);
90    align_impl!(0b00000000_00000000_01000000_00000000);
91    align_impl!(0b00000000_00000000_10000000_00000000);
92    align_impl!(0b00000000_00000001_00000000_00000000);
93    align_impl!(0b00000000_00000010_00000000_00000000);
94    align_impl!(0b00000000_00000100_00000000_00000000);
95    align_impl!(0b00000000_00001000_00000000_00000000);
96    align_impl!(0b00000000_00010000_00000000_00000000);
97    align_impl!(0b00000000_00100000_00000000_00000000);
98    align_impl!(0b00000000_01000000_00000000_00000000);
99    align_impl!(0b00000000_10000000_00000000_00000000);
100    align_impl!(0b00000001_00000000_00000000_00000000);
101    align_impl!(0b00000010_00000000_00000000_00000000);
102    align_impl!(0b00000100_00000000_00000000_00000000);
103    align_impl!(0b00001000_00000000_00000000_00000000);
104    align_impl!(0b00010000_00000000_00000000_00000000);
105    align_impl!(0b00100000_00000000_00000000_00000000);
106}
107
108impl<const N: usize> core::hash::Hash for Align<N>
109where
110    Self: Alignment,
111{
112    #[inline(always)]
113    fn hash<H: core::hash::Hasher>(&self, _: &mut H) {}
114}
115
116impl<const N: usize> core::cmp::Ord for Align<N>
117where
118    Self: Alignment,
119{
120    #[inline(always)]
121    fn cmp(&self, _: &Self) -> core::cmp::Ordering {
122        core::cmp::Ordering::Equal
123    }
124}
125
126impl<const N: usize> core::cmp::PartialOrd<Self> for Align<N>
127where
128    Self: Alignment,
129{
130    #[inline(always)]
131    fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
132        Some(self.cmp(other))
133    }
134}
135
136impl<const N: usize> core::fmt::Display for Align<N>
137where
138    Self: Alignment,
139{
140    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
141        write!(f, "Align<{N}>")
142    }
143}
144
145const _: () = const {
146    assert!(align_of::<Align<1>>() == 1, "Align(1) is expected to be of alignment 1");
147    assert!(size_of::<Align<1>>() == 0, "Align(1) is expected to be of size 0");
148    assert!(align_of::<Align<2>>() == 2, "Align(2) is expected to be of alignment 2");
149    assert!(size_of::<Align<2>>() == 0, "Align(2) is expected to be of size 0");
150    assert!(align_of::<Align<4>>() == 4, "Align(4) is expected to be of alignment 4");
151    assert!(size_of::<Align<4>>() == 0, "Align(4) is expected to be of size 0");
152    assert!(align_of::<Align<8>>() == 8, "Align(8) is expected to be of alignment 8");
153    assert!(size_of::<Align<8>>() == 0, "Align(8) is expected to be of size 0");
154    assert!(
155        align_of::<Align<16>>() == 16,
156        "Align(16) is expected to be of alignment 16"
157    );
158    assert!(size_of::<Align<16>>() == 0, "Align(16) is expected to be of size 0");
159    assert!(
160        align_of::<Align<32>>() == 32,
161        "Align(32) is expected to be of alignment 32"
162    );
163    assert!(size_of::<Align<32>>() == 0, "Align(32) is expected to be of size 0");
164    assert!(
165        align_of::<Align<64>>() == 64,
166        "Align(64) is expected to be of alignment 64"
167    );
168    assert!(size_of::<Align<64>>() == 0, "Align(64) is expected to be of size 0");
169    assert!(
170        align_of::<Align<128>>() == 128,
171        "Align(128) is expected to be of alignment 128"
172    );
173    assert!(size_of::<Align<128>>() == 0, "Align(128) is expected to be of size 0");
174    assert!(
175        align_of::<Align<256>>() == 256,
176        "Align(256) is expected to be of alignment 256"
177    );
178    assert!(size_of::<Align<256>>() == 0, "Align(256) is expected to be of size 0");
179    assert!(
180        align_of::<Align<512>>() == 512,
181        "Align(512) is expected to be of alignment 512"
182    );
183    assert!(size_of::<Align<512>>() == 0, "Align(512) is expected to be of size 0");
184    assert!(
185        align_of::<Align<1024>>() == 1024,
186        "Align(1024) is expected to be of alignment 1024"
187    );
188    assert!(size_of::<Align<1024>>() == 0, "Align(1024) is expected to be of size 0");
189    assert!(
190        align_of::<Align<2048>>() == 2048,
191        "Align(2048) is expected to be of alignment 2048"
192    );
193    assert!(size_of::<Align<2048>>() == 0, "Align(2048) is expected to be of size 0");
194    assert!(
195        align_of::<Align<4096>>() == 4096,
196        "Align(4096) is expected to be of alignment 4096"
197    );
198    assert!(size_of::<Align<4096>>() == 0, "Align(4096) is expected to be of size 0");
199    assert!(
200        align_of::<Align<8192>>() == 8192,
201        "Align(8192) is expected to be of alignment 8192"
202    );
203    assert!(size_of::<Align<8192>>() == 0, "Align(8192) is expected to be of size 0");
204    assert!(
205        align_of::<Align<16384>>() == 16384,
206        "Align(16384) is expected to be of alignment 16384"
207    );
208    assert!(
209        size_of::<Align<16384>>() == 0,
210        "Align(16384) is expected to be of size 0"
211    );
212    assert!(
213        align_of::<Align<32768>>() == 32768,
214        "Align(32768) is expected to be of alignment 32768"
215    );
216    assert!(
217        size_of::<Align<32768>>() == 0,
218        "Align(32768) is expected to be of size 0"
219    );
220    assert!(
221        align_of::<Align<65536>>() == 65536,
222        "Align(65536) is expected to be of alignment 65536"
223    );
224    assert!(
225        size_of::<Align<65536>>() == 0,
226        "Align(65536) is expected to be of size 0"
227    );
228    assert!(
229        align_of::<Align<131072>>() == 131072,
230        "Align(131072) is expected to be of alignment 131072"
231    );
232    assert!(
233        size_of::<Align<131072>>() == 0,
234        "Align(131072) is expected to be of size 0"
235    );
236    assert!(
237        align_of::<Align<262144>>() == 262144,
238        "Align(262144) is expected to be of alignment 262144"
239    );
240    assert!(
241        size_of::<Align<262144>>() == 0,
242        "Align(262144) is expected to be of size 0"
243    );
244    assert!(
245        align_of::<Align<524288>>() == 524288,
246        "Align(524288) is expected to be of alignment 524288"
247    );
248    assert!(
249        size_of::<Align<524288>>() == 0,
250        "Align(524288) is expected to be of size 0"
251    );
252    assert!(
253        align_of::<Align<1048576>>() == 1048576,
254        "Align(1048576) is expected to be of alignment 1048576"
255    );
256    assert!(
257        size_of::<Align<1048576>>() == 0,
258        "Align(1048576) is expected to be of size 0"
259    );
260    assert!(
261        align_of::<Align<2097152>>() == 2097152,
262        "Align(2097152) is expected to be of alignment 2097152"
263    );
264    assert!(
265        size_of::<Align<2097152>>() == 0,
266        "Align(2097152) is expected to be of size 0"
267    );
268    assert!(
269        align_of::<Align<4194304>>() == 4194304,
270        "Align(4194304) is expected to be of alignment 4194304"
271    );
272    assert!(
273        size_of::<Align<4194304>>() == 0,
274        "Align(4194304) is expected to be of size 0"
275    );
276    assert!(
277        align_of::<Align<8388608>>() == 8388608,
278        "Align(8388608) is expected to be of alignment 8388608"
279    );
280    assert!(
281        size_of::<Align<8388608>>() == 0,
282        "Align(8388608) is expected to be of size 0"
283    );
284    assert!(
285        align_of::<Align<16777216>>() == 16777216,
286        "Align(16777216) is expected to be of alignment 16777216"
287    );
288    assert!(
289        size_of::<Align<16777216>>() == 0,
290        "Align(16777216) is expected to be of size 0"
291    );
292    assert!(
293        align_of::<Align<33554432>>() == 33554432,
294        "Align(33554432) is expected to be of alignment 33554432"
295    );
296    assert!(
297        size_of::<Align<33554432>>() == 0,
298        "Align(33554432) is expected to be of size 0"
299    );
300    assert!(
301        align_of::<Align<67108864>>() == 67108864,
302        "Align(67108864) is expected to be of alignment 67108864"
303    );
304    assert!(
305        size_of::<Align<67108864>>() == 0,
306        "Align(67108864) is expected to be of size 0"
307    );
308    assert!(
309        align_of::<Align<134217728>>() == 134217728,
310        "Align(134217728) is expected to be of alignment 134217728"
311    );
312    assert!(
313        size_of::<Align<134217728>>() == 0,
314        "Align(134217728) is expected to be of size 0"
315    );
316    assert!(
317        align_of::<Align<268435456>>() == 268435456,
318        "Align(268435456) is expected to be of alignment 268435456"
319    );
320    assert!(
321        size_of::<Align<268435456>>() == 0,
322        "Align(268435456) is expected to be of size 0"
323    );
324    assert!(
325        align_of::<Align<536870912>>() == 536870912,
326        "Align(536870912) is expected to be of alignment 536870912"
327    );
328    assert!(
329        size_of::<Align<536870912>>() == 0,
330        "Align(536870912) is expected to be of size 0"
331    );
332};