[go: up one dir, main page]

elain/
lib.rs

1//! Set the minimum alignments of types using const generics, rather
2//! than `#[repr(align(N))]`.
3//!
4//! ## Basic Use
5//! The type [`Align<N>`](Align) is a zero-sized-type with alignment
6//! equal to `N`:
7//! ```
8//! use elain::Align;
9//! use core::mem::{align_of, align_of_val};
10//!
11//! assert_eq!(align_of::<Align<1>>(), 1);
12//! assert_eq!(align_of::<Align<2>>(), 2);
13//! assert_eq!(align_of::<Align<4>>(), 4);
14//!
15//! const FOO_ALIGN: usize = 8;
16//!
17//! #[repr(C)]
18//! struct Foo {
19//!     _align: Align<FOO_ALIGN>,
20//! }
21//!
22//! let foo: Foo = Foo { _align: Align::NEW };
23//!
24//! assert_eq!(align_of_val(&foo), 8);
25//! ```
26//!
27//! Valid alignments are powers of two less-than-or-equal to 2<sup>29</sup>.
28//! Supplying an *invalid* alignment to [`Align`] is a type error:
29//! ```compile_fail
30//! use elain::Align;
31//!
32//! struct Foo(Align<3>); // Compile Error
33//! ```
34//!
35//! ## Generic Use
36//! Because only *some* integers are valid alignments, supplying the
37//! alignment of a type generically requires some extra work:
38//! ```compile_fail
39//! use elain::Align;
40//!
41//! #[repr(C)]
42//! struct Foo<const N: usize> {
43//!     _align: Align<N>,
44//! }
45//! ```
46//! To resolve this error, add a `where` bound like so, using the
47//! [`Alignment`] trait to check that [`Align<N>`](Align) is valid.
48//!
49//! ```
50//! use elain::{Align, Alignment};
51//! use core::mem::align_of;
52//!
53//! #[repr(C)]
54//! struct Foo<const MIN_ALIGNMENT: usize>
55//! where
56//!     Align<MIN_ALIGNMENT>: Alignment
57//! {
58//!     _align: Align<MIN_ALIGNMENT>,
59//!     bar: u8,
60//!     baz: u16,
61//! }
62//!
63//! assert_eq!(align_of::<Foo<1>>(), 2);
64//! assert_eq!(align_of::<Foo<2>>(), 2);
65//! assert_eq!(align_of::<Foo<4>>(), 4);
66//! ```
67#![no_std]
68use core::{
69    cmp::{Ordering, PartialOrd},
70    fmt::{self, Debug},
71    hash::{Hash, Hasher},
72};
73
74/// A zero-sized-type aligned to `N`. Compound types containing a
75/// field `Align<N>` with have an alignment of *at least* `N`.
76///
77/// ```
78/// use elain::Align;
79/// use core::mem::{align_of, align_of_val};
80///
81/// assert_eq!(align_of::<Align<1>>(), 1);
82/// assert_eq!(align_of::<Align<2>>(), 2);
83/// assert_eq!(align_of::<Align<4>>(), 4);
84///
85/// const FOO_ALIGN: usize = 8;
86///
87/// #[repr(C)]
88/// struct Foo {
89///     _align: Align<FOO_ALIGN>,
90/// }
91///
92/// let foo: Foo = Foo { _align: Align::NEW };
93///
94/// assert_eq!(align_of_val(&foo), 8);
95/// ```
96// NB: `Eq` and `PartialEq` are derived so that `Align` also
97// implements `StructuralEq` and `PartialStructuralEq`, which makes
98// `Align` usable as a const generic type. Just in case.
99#[derive(Eq, PartialEq)]
100#[repr(transparent)]
101pub struct Align<const N: usize>([<Self as private::Sealed>::Archetype; 0])
102where
103    Self: Alignment;
104
105impl<const N: usize> Align<N>
106where
107    Self: Alignment,
108{
109    /// An instance of `Align<N>`.
110    /// ```
111    /// use elain::Align;
112    /// use core::mem::{align_of, align_of_val};
113    ///
114    /// #[repr(C)]
115    /// struct Foo {
116    ///     _align: Align<8>,
117    /// }
118    ///
119    /// let foo: Foo = Foo { _align: Align::NEW };
120    ///
121    /// assert_eq!(align_of_val(&foo), 8);
122    /// ```
123    pub const NEW: Self = Self([]);
124}
125
126/// Implemented for all [`Align<N>`](Align) where `N` is a
127/// valid alignment (i.e., a power of two less-than-or-equal to
128/// 2<sup>28</sup>).
129///
130/// ```
131/// use elain::{Align, Alignment};
132/// use core::mem::align_of;
133///
134/// #[repr(C)]
135/// struct Foo<const MIN_ALIGNMENT: usize>
136/// where
137///     Align<MIN_ALIGNMENT>: Alignment
138/// {
139///     _align: Align<MIN_ALIGNMENT>,
140///     bar: u8,
141///     baz: u16,
142/// }
143///
144/// assert_eq!(align_of::<Foo<1>>(), 2);
145/// assert_eq!(align_of::<Foo<2>>(), 2);
146/// assert_eq!(align_of::<Foo<4>>(), 4);
147/// ```
148pub unsafe trait Alignment: private::Sealed {}
149
150mod private {
151    /// This trait is used internally to map an `Align<N>` to a unit
152    /// struct of alignment N.
153    pub trait Sealed {
154        /// A zero-sized type of particular alignment.
155        type Archetype: Copy + Eq + PartialEq + Send + Sync + Unpin;
156    }
157
158    #[rustfmt::skip] impl Sealed for super::Align<        1> { type Archetype = Align1;         }
159    #[rustfmt::skip] impl Sealed for super::Align<        2> { type Archetype = Align2;         }
160    #[rustfmt::skip] impl Sealed for super::Align<        4> { type Archetype = Align4;         }
161    #[rustfmt::skip] impl Sealed for super::Align<        8> { type Archetype = Align8;         }
162    #[rustfmt::skip] impl Sealed for super::Align<       16> { type Archetype = Align16;        }
163    #[rustfmt::skip] impl Sealed for super::Align<       32> { type Archetype = Align32;        }
164    #[rustfmt::skip] impl Sealed for super::Align<       64> { type Archetype = Align64;        }
165    #[rustfmt::skip] impl Sealed for super::Align<      128> { type Archetype = Align128;       }
166    #[rustfmt::skip] impl Sealed for super::Align<      256> { type Archetype = Align256;       }
167    #[rustfmt::skip] impl Sealed for super::Align<      512> { type Archetype = Align512;       }
168    #[rustfmt::skip] impl Sealed for super::Align<     1024> { type Archetype = Align1024;      }
169    #[rustfmt::skip] impl Sealed for super::Align<     2048> { type Archetype = Align2048;      }
170    #[rustfmt::skip] impl Sealed for super::Align<     4096> { type Archetype = Align4096;      }
171    #[rustfmt::skip] impl Sealed for super::Align<     8192> { type Archetype = Align8192;      }
172    #[rustfmt::skip] impl Sealed for super::Align<    16384> { type Archetype = Align16384;     }
173    #[rustfmt::skip] impl Sealed for super::Align<    32768> { type Archetype = Align32768;     }
174    #[rustfmt::skip] impl Sealed for super::Align<    65536> { type Archetype = Align65536;     }
175    #[rustfmt::skip] impl Sealed for super::Align<   131072> { type Archetype = Align131072;    }
176    #[rustfmt::skip] impl Sealed for super::Align<   262144> { type Archetype = Align262144;    }
177    #[rustfmt::skip] impl Sealed for super::Align<   524288> { type Archetype = Align524288;    }
178    #[rustfmt::skip] impl Sealed for super::Align<  1048576> { type Archetype = Align1048576;   }
179    #[rustfmt::skip] impl Sealed for super::Align<  2097152> { type Archetype = Align2097152;   }
180    #[rustfmt::skip] impl Sealed for super::Align<  4194304> { type Archetype = Align4194304;   }
181    #[rustfmt::skip] impl Sealed for super::Align<  8388608> { type Archetype = Align8388608;   }
182    #[rustfmt::skip] impl Sealed for super::Align< 16777216> { type Archetype = Align16777216;  }
183    #[rustfmt::skip] impl Sealed for super::Align< 33554432> { type Archetype = Align33554432;  }
184    #[rustfmt::skip] impl Sealed for super::Align< 67108864> { type Archetype = Align67108864;  }
185    #[rustfmt::skip] impl Sealed for super::Align<134217728> { type Archetype = Align134217728; }
186    #[rustfmt::skip] impl Sealed for super::Align<268435456> { type Archetype = Align268435456; }
187    #[rustfmt::skip] impl Sealed for super::Align<536870912> { type Archetype = Align536870912; }
188
189    // NB: It'd be great if these could be void enums, as doing so
190    // greatly simplifies the expansion of derived traits.
191    #[rustfmt::skip] #[derive(Copy, Clone, Eq, PartialEq)] #[repr(align(        1))] pub struct Align1         {}
192    #[rustfmt::skip] #[derive(Copy, Clone, Eq, PartialEq)] #[repr(align(        2))] pub struct Align2         {}
193    #[rustfmt::skip] #[derive(Copy, Clone, Eq, PartialEq)] #[repr(align(        4))] pub struct Align4         {}
194    #[rustfmt::skip] #[derive(Copy, Clone, Eq, PartialEq)] #[repr(align(        8))] pub struct Align8         {}
195    #[rustfmt::skip] #[derive(Copy, Clone, Eq, PartialEq)] #[repr(align(       16))] pub struct Align16        {}
196    #[rustfmt::skip] #[derive(Copy, Clone, Eq, PartialEq)] #[repr(align(       32))] pub struct Align32        {}
197    #[rustfmt::skip] #[derive(Copy, Clone, Eq, PartialEq)] #[repr(align(       64))] pub struct Align64        {}
198    #[rustfmt::skip] #[derive(Copy, Clone, Eq, PartialEq)] #[repr(align(      128))] pub struct Align128       {}
199    #[rustfmt::skip] #[derive(Copy, Clone, Eq, PartialEq)] #[repr(align(      256))] pub struct Align256       {}
200    #[rustfmt::skip] #[derive(Copy, Clone, Eq, PartialEq)] #[repr(align(      512))] pub struct Align512       {}
201    #[rustfmt::skip] #[derive(Copy, Clone, Eq, PartialEq)] #[repr(align(     1024))] pub struct Align1024      {}
202    #[rustfmt::skip] #[derive(Copy, Clone, Eq, PartialEq)] #[repr(align(     2048))] pub struct Align2048      {}
203    #[rustfmt::skip] #[derive(Copy, Clone, Eq, PartialEq)] #[repr(align(     4096))] pub struct Align4096      {}
204    #[rustfmt::skip] #[derive(Copy, Clone, Eq, PartialEq)] #[repr(align(     8192))] pub struct Align8192      {}
205    #[rustfmt::skip] #[derive(Copy, Clone, Eq, PartialEq)] #[repr(align(    16384))] pub struct Align16384     {}
206    #[rustfmt::skip] #[derive(Copy, Clone, Eq, PartialEq)] #[repr(align(    32768))] pub struct Align32768     {}
207    #[rustfmt::skip] #[derive(Copy, Clone, Eq, PartialEq)] #[repr(align(    65536))] pub struct Align65536     {}
208    #[rustfmt::skip] #[derive(Copy, Clone, Eq, PartialEq)] #[repr(align(   131072))] pub struct Align131072    {}
209    #[rustfmt::skip] #[derive(Copy, Clone, Eq, PartialEq)] #[repr(align(   262144))] pub struct Align262144    {}
210    #[rustfmt::skip] #[derive(Copy, Clone, Eq, PartialEq)] #[repr(align(   524288))] pub struct Align524288    {}
211    #[rustfmt::skip] #[derive(Copy, Clone, Eq, PartialEq)] #[repr(align(  1048576))] pub struct Align1048576   {}
212    #[rustfmt::skip] #[derive(Copy, Clone, Eq, PartialEq)] #[repr(align(  2097152))] pub struct Align2097152   {}
213    #[rustfmt::skip] #[derive(Copy, Clone, Eq, PartialEq)] #[repr(align(  4194304))] pub struct Align4194304   {}
214    #[rustfmt::skip] #[derive(Copy, Clone, Eq, PartialEq)] #[repr(align(  8388608))] pub struct Align8388608   {}
215    #[rustfmt::skip] #[derive(Copy, Clone, Eq, PartialEq)] #[repr(align( 16777216))] pub struct Align16777216  {}
216    #[rustfmt::skip] #[derive(Copy, Clone, Eq, PartialEq)] #[repr(align( 33554432))] pub struct Align33554432  {}
217    #[rustfmt::skip] #[derive(Copy, Clone, Eq, PartialEq)] #[repr(align( 67108864))] pub struct Align67108864  {}
218    #[rustfmt::skip] #[derive(Copy, Clone, Eq, PartialEq)] #[repr(align(134217728))] pub struct Align134217728 {}
219    #[rustfmt::skip] #[derive(Copy, Clone, Eq, PartialEq)] #[repr(align(268435456))] pub struct Align268435456 {}
220    #[rustfmt::skip] #[derive(Copy, Clone, Eq, PartialEq)] #[repr(align(536870912))] pub struct Align536870912 {}
221}
222
223// NB: While these impls could be reduced to a single:
224//    unsafe impl<const N: usize> Alignment for Align<N>
225//    where
226//        Self: private::Sealed
227//    {}
228// …leaving them enumerated makes explicit what alignments are valid.
229#[rustfmt::skip] unsafe impl Alignment for Align<        1> {}
230#[rustfmt::skip] unsafe impl Alignment for Align<        2> {}
231#[rustfmt::skip] unsafe impl Alignment for Align<        4> {}
232#[rustfmt::skip] unsafe impl Alignment for Align<        8> {}
233#[rustfmt::skip] unsafe impl Alignment for Align<       16> {}
234#[rustfmt::skip] unsafe impl Alignment for Align<       32> {}
235#[rustfmt::skip] unsafe impl Alignment for Align<       64> {}
236#[rustfmt::skip] unsafe impl Alignment for Align<      128> {}
237#[rustfmt::skip] unsafe impl Alignment for Align<      256> {}
238#[rustfmt::skip] unsafe impl Alignment for Align<      512> {}
239#[rustfmt::skip] unsafe impl Alignment for Align<     1024> {}
240#[rustfmt::skip] unsafe impl Alignment for Align<     2048> {}
241#[rustfmt::skip] unsafe impl Alignment for Align<     4096> {}
242#[rustfmt::skip] unsafe impl Alignment for Align<     8192> {}
243#[rustfmt::skip] unsafe impl Alignment for Align<    16384> {}
244#[rustfmt::skip] unsafe impl Alignment for Align<    32768> {}
245#[rustfmt::skip] unsafe impl Alignment for Align<    65536> {}
246#[rustfmt::skip] unsafe impl Alignment for Align<   131072> {}
247#[rustfmt::skip] unsafe impl Alignment for Align<   262144> {}
248#[rustfmt::skip] unsafe impl Alignment for Align<   524288> {}
249#[rustfmt::skip] unsafe impl Alignment for Align<  1048576> {}
250#[rustfmt::skip] unsafe impl Alignment for Align<  2097152> {}
251#[rustfmt::skip] unsafe impl Alignment for Align<  4194304> {}
252#[rustfmt::skip] unsafe impl Alignment for Align<  8388608> {}
253#[rustfmt::skip] unsafe impl Alignment for Align< 16777216> {}
254#[rustfmt::skip] unsafe impl Alignment for Align< 33554432> {}
255#[rustfmt::skip] unsafe impl Alignment for Align< 67108864> {}
256#[rustfmt::skip] unsafe impl Alignment for Align<134217728> {}
257#[rustfmt::skip] unsafe impl Alignment for Align<268435456> {}
258#[rustfmt::skip] unsafe impl Alignment for Align<536870912> {}
259
260// NB: These traits are implemented explicitly, rather than derived,
261// because their implementations do not depend on `Align`'s field.
262
263impl<const N: usize> Copy for Align<N> where Self: Alignment {}
264
265impl<const N: usize> Clone for Align<N>
266where
267    Self: Alignment,
268{
269    #[inline(always)]
270    fn clone(&self) -> Self {
271        *self
272    }
273}
274
275impl<const N: usize> Debug for Align<N>
276where
277    Self: Alignment,
278{
279    #[inline]
280    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
281        f.write_str(core::any::type_name::<Self>())
282    }
283}
284
285impl<const N: usize> Default for Align<N>
286where
287    Self: Alignment,
288{
289    #[inline(always)]
290    fn default() -> Self {
291        Self([])
292    }
293}
294
295impl<const N: usize> Hash for Align<N>
296where
297    Self: Alignment,
298{
299    #[inline(always)]
300    fn hash<H: Hasher>(&self, _: &mut H) {}
301}
302
303impl<const N: usize> Ord for Align<N>
304where
305    Self: Alignment,
306{
307    #[inline(always)]
308    fn cmp(&self, _: &Self) -> Ordering {
309        Ordering::Equal
310    }
311}
312
313impl<const N: usize> PartialOrd<Self> for Align<N>
314where
315    Self: Alignment,
316{
317    #[inline(always)]
318    fn partial_cmp(&self, _: &Self) -> Option<Ordering> {
319        Some(Ordering::Equal)
320    }
321}