zephyr/
align.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
//! Alignment
//!
//! Natively, the align attribute in rust does not allow anything other than an integer literal.
//! However, Zephyr will define the external alignment based on numeric constants.  This defines a
//! bit of a trick to enforce alignment of structs to values by defined constants.
//!
//! Thanks to Chayim Refael Friedman for help with this.

#[doc(hidden)]
pub struct AlignAsStruct;

#[doc(hidden)]
pub trait AlignAsTrait<const N: usize> {
    type Aligned;
}

macro_rules! impl_alignas {
    ( $($align:literal),* $(,)? ) => {
        $(
            const _: () = {
                #[repr(align($align))]
                pub struct Aligned;
                impl AlignAsTrait<$align> for AlignAsStruct {
                    type Aligned = Aligned;
                }
            };
        )*
    };
}
// This can be expanded as needed.
impl_alignas!(1, 2, 4, 8, 16, 32, 64, 128, 256);

/// Align a given struct to a given alignment.  To use this, just include `AlignAs<N>` as the first
/// member of the struct.
#[repr(transparent)]
pub struct AlignAs<const N: usize>([<AlignAsStruct as AlignAsTrait<N>>::Aligned; 0])
    where
    AlignAsStruct: AlignAsTrait<N>;

impl<const N: usize> AlignAs<N>
    where AlignAsStruct: AlignAsTrait<N>
{
    /// Construct a new AlignAs.
    ///
    /// It is zero bytes, but needs a constructor as the field is private.
    pub const fn new() -> AlignAs<N> {
        AlignAs([])
    }
}