cuneiform_fields/
alignas.rs

1//!
2//! Types that have forced alignment size desired by the user.
3//!
4//! For the rough CXX equivalent of this code: <https://en.cppreference.com/w/cpp/language/alignas>
5
6use core::fmt;
7use core::ops::{Deref, DerefMut};
8
9#[doc(hidden)]
10macro_rules! impl_align_as {
11    ($size:expr, $si:ident) => {
12        ///
13        /// Applies predetermined alignment size to an object.
14        ///
15        /// CXX equivalent is: <https://en.cppreference.com/w/cpp/language/alignas>
16        #[repr(align($size))]
17        pub struct $si<T> {
18            value: T,
19        }
20
21        unsafe impl<T: Send> Send for $si<T> {}
22        unsafe impl<T: Sync> Sync for $si<T> {}
23
24        impl<T> $si<T> {
25            /// Applies alignment with $size bytes to given data.
26            ///
27            /// # Examples
28            ///
29            /// ```
30            /// use cuneiform_fields::alignas::AlignAs8;
31            ///
32            /// let padded = AlignAs8::new(1);
33            /// ```
34            pub fn new(t: T) -> $si<T> {
35                $si::<T> { value: t }
36            }
37
38            /// Returns the inner value.
39            ///
40            /// # Examples
41            ///
42            /// ```
43            /// use cuneiform_fields::alignas::AlignAs8;
44            ///
45            /// let padded = AlignAs8::new(7);
46            /// let value = padded.into_inner();
47            /// assert_eq!(value, 7);
48            /// ```
49            pub fn into_inner(self) -> T {
50                self.value
51            }
52        }
53
54        impl<T> Deref for $si<T> {
55            type Target = T;
56
57            fn deref(&self) -> &T {
58                &self.value
59            }
60        }
61
62        impl<T> DerefMut for $si<T> {
63            fn deref_mut(&mut self) -> &mut T {
64                &mut self.value
65            }
66        }
67
68        impl<T: fmt::Debug> fmt::Debug for $si<T> {
69            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
70                f.debug_struct("$si").field("value", &self.value).finish()
71            }
72        }
73
74        impl<T> From<T> for $si<T> {
75            fn from(t: T) -> Self {
76                $si::new(t)
77            }
78        }
79    };
80}
81
82#[doc(hidden)]
83macro_rules! generate_align_as {
84    ($($n: expr => $si: ident),*) => {
85        $(impl_align_as!{$n, $si})*
86    };
87}
88
89// 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768]
90generate_align_as! {
91    2  => AlignAs2,
92    4  => AlignAs4,
93    8  => AlignAs8,
94    16  => AlignAs16,
95    32  => AlignAs32,
96    64  => AlignAs64,
97    128  => AlignAs128,
98    256  => AlignAs256,
99    512  => AlignAs512,
100    1024  => AlignAs1024,
101    2048  => AlignAs2048,
102    4096  => AlignAs4096,
103    8192  => AlignAs8192,
104    16384  => AlignAs16384,
105    32768  => AlignAs32768
106}
107
108mod alignas_tests {
109    use crate::alignas::AlignAs32768;
110    #[allow(dead_code)]
111    struct Naber(AlignAs32768<u8>);
112
113    #[test]
114    fn test_alignas_32768() {
115        assert_eq!(core::mem::align_of::<Naber>(), 32768);
116    }
117}