offline/
core.rs

1//! Things that only require [`core`].
2//!
3//! [`core`]: ::core
4use core::{fmt, marker::PhantomData, mem, num::NonZero, ops, ptr};
5
6/// Alias for [`Align::new`].
7///
8/// # Examples
9///
10/// ```
11/// let aligner = offline::align::<16>();
12/// ```
13pub const fn align<const N: usize>() -> Align<N>
14where
15    Align<N>: Alignment,
16{
17    Align::new()
18}
19
20/// Alias for [`Padding::new`].
21///
22/// # Examples
23///
24/// ```
25/// let padding = offline::padding::<16>();
26/// ```
27pub const fn padding<const N: usize>() -> Padding<N>
28where
29    Align<N>: Alignment,
30{
31    Padding::new()
32}
33
34/// Alias for [`Aligned::new`].
35///
36/// # Examples
37///
38/// ```
39/// let aligned = offline::aligned::<[u8; 3], 16>([1, 2, 3]);
40/// ```
41pub const fn aligned<T, const N: usize>(value: T) -> Aligned<T, N>
42where
43    Align<N>: Alignment,
44{
45    Aligned::new(value)
46}
47
48/// Alias for [`Misaligned::new`].
49///
50/// # Examples
51///
52/// ```
53/// let misaligned = offline::misaligned::<[u8; 3], 16>([1, 2, 3]);
54/// ```
55pub const fn misaligned<T: Unpadded, const N: usize>(value: T) -> Misaligned<T, N>
56where
57    Align<N>: Alignment,
58{
59    Misaligned::new(value)
60}
61
62/// Struct aligned to a particular number of bytes.
63///
64/// Because `repr(Rust)` allows rearranging fields, you should use [`Aligned`]
65/// instead if you want to actually ensure that a particular value is aligned.
66/// Otherwise, a field of this type simple ensures that its containing struct
67/// is aligned, potentially leaving some fields unaligned.
68#[derive(Copy, Clone)]
69pub struct Align<const N: usize>([<Self as Alignment>::Align; 0])
70where
71    Align<N>: Alignment;
72impl<const N: usize> Align<N>
73where
74    Align<N>: Alignment,
75{
76    /// Makes an alignment.
77    #[inline]
78    pub const fn new() -> Align<N> {
79        Align([])
80    }
81}
82impl<const N: usize> fmt::Debug for Align<N>
83where
84    Align<N>: Alignment,
85{
86    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
87        let (buf, len) = const {
88            let mut buf = *b"Align<{1 << 63}>";
89            let len = if N < (1 << 10) {
90                buf[12] = b'0' + (N.trailing_zeros() as u8);
91                buf[13] = b'}';
92                buf[14] = b'>';
93                15
94            } else {
95                let exp = N.trailing_zeros() as u8;
96                buf[12] = b'0' + (exp / 10);
97                buf[13] = b'0' + (exp % 10);
98                16
99            };
100            (buf, len)
101        };
102
103        // SAFETY: We only output valid UTF-8.
104        let s = unsafe { str::from_utf8_unchecked(&buf[..len]) };
105        f.pad(s)
106    }
107}
108
109/// Uninitialized bytes with a particular alignment.
110///
111/// Unlike regular padding, all bytes of this padding are guaranteed to be
112/// preserved across copies.
113#[derive(Copy, Clone)]
114pub struct Padding<const N: usize>(mem::MaybeUninit<<Align<N> as Alignment>::Padding>)
115where
116    Align<N>: Alignment;
117impl<const N: usize> Padding<N>
118where
119    Align<N>: Alignment,
120{
121    /// Makes padding.
122    #[inline]
123    pub const fn new() -> Padding<N> {
124        Padding(mem::MaybeUninit::uninit())
125    }
126}
127impl<const N: usize> fmt::Debug for Padding<N>
128where
129    Align<N>: Alignment,
130{
131    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
132        let (buf, len) = const {
133            let mut buf = *b"Padding<{1 << 63}>";
134            let len = if N < (1 << 10) {
135                buf[14] = b'0' + (N.trailing_zeros() as u8);
136                buf[15] = b'}';
137                buf[16] = b'>';
138                17
139            } else {
140                let exp = N.trailing_zeros() as u8;
141                buf[14] = b'0' + (exp / 10);
142                buf[15] = b'0' + (exp % 10);
143                18
144            };
145            (buf, len)
146        };
147
148        // SAFETY: We only output valid UTF-8.
149        let s = unsafe { str::from_utf8_unchecked(&buf[..len]) };
150        f.pad(s)
151    }
152}
153
154/// Sealed module.
155mod sealed {
156    /// Sealed trait.
157    pub trait Sealed {}
158}
159
160/// Valid [`Align`]ment.
161///
162/// Due to restrictions in the compiler, this only allows alignments up to
163/// 2<sup>29</sup>. The alignments between 2<sup>16</sup> are conditional on
164/// the target pointer width being 32 bits or higher.
165pub trait Alignment: sealed::Sealed {
166    /// Type which satisfies the alignment.
167    #[doc(hidden)]
168    type Align: 'static + Copy;
169
170    /// Padding for the alignment of a particular type.
171    #[doc(hidden)]
172    type Padding: 'static + Copy;
173}
174
175/// Creates "aligner" structs which have a specified alignment.
176macro_rules! align {
177    (
178        $($vis:vis struct $A:ident = $align:literal;)*
179    ) => {
180        $(
181            #[repr(align($align))]
182            #[allow(missing_debug_implementations)]
183            #[derive(Copy, Clone)]
184            $vis struct $A;
185
186            impl sealed::Sealed for Align<$align> {}
187            impl Alignment for Align<$align> {
188                type Align = $A;
189                type Padding = [u8; $align];
190            }
191        )*
192    }
193}
194
195align! {
196    pub struct A0 = 0x1;
197    pub struct A1 = 0x2;
198    pub struct A2 = 0x4;
199    pub struct A3 = 0x8;
200    pub struct A4 = 0x10;
201    pub struct A5 = 0x20;
202    pub struct A6 = 0x40;
203    pub struct A7 = 0x80;
204    pub struct A8 = 0x100;
205    pub struct A9 = 0x200;
206    pub struct A10 = 0x400;
207    pub struct A11 = 0x800;
208    pub struct A12 = 0x1000;
209    pub struct A13 = 0x2000;
210    pub struct A14 = 0x4000;
211    pub struct A15 = 0x8000;
212}
213#[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))]
214align! {
215    pub struct A16 = 0x10000;
216    pub struct A17 = 0x20000;
217    pub struct A18 = 0x40000;
218    pub struct A19 = 0x80000;
219    pub struct A20 = 0x100000;
220    pub struct A21 = 0x200000;
221    pub struct A22 = 0x400000;
222    pub struct A23 = 0x800000;
223    pub struct A24 = 0x1000000;
224    pub struct A25 = 0x2000000;
225    pub struct A26 = 0x4000000;
226    pub struct A27 = 0x8000000;
227    pub struct A28 = 0x10000000;
228    pub struct A29 = 0x20000000;
229    /*
230    pub struct A30 = 0x40000000;
231    pub struct A31 = 0x80000000;
232    */
233}
234/*
235#[cfg(target_pointer_width = "64")]
236aligner! {
237    pub struct A32 = 0x100000000;
238    pub struct A33 = 0x200000000;
239    pub struct A34 = 0x400000000;
240    pub struct A35 = 0x800000000;
241    pub struct A36 = 0x1000000000;
242    pub struct A37 = 0x2000000000;
243    pub struct A38 = 0x4000000000;
244    pub struct A39 = 0x8000000000;
245    pub struct A40 = 0x10000000000;
246    pub struct A41 = 0x20000000000;
247    pub struct A42 = 0x40000000000;
248    pub struct A43 = 0x80000000000;
249    pub struct A44 = 0x100000000000;
250    pub struct A45 = 0x200000000000;
251    pub struct A46 = 0x400000000000;
252    pub struct A47 = 0x800000000000;
253    pub struct A48 = 0x1000000000000;
254    pub struct A49 = 0x2000000000000;
255    pub struct A50 = 0x4000000000000;
256    pub struct A51 = 0x8000000000000;
257    pub struct A52 = 0x10000000000000;
258    pub struct A53 = 0x20000000000000;
259    pub struct A54 = 0x40000000000000;
260    pub struct A55 = 0x80000000000000;
261    pub struct A56 = 0x100000000000000;
262    pub struct A57 = 0x200000000000000;
263    pub struct A58 = 0x400000000000000;
264    pub struct A59 = 0x800000000000000;
265    pub struct A60 = 0x1000000000000000;
266    pub struct A61 = 0x2000000000000000;
267    pub struct A62 = 0x4000000000000000;
268    pub struct A63 = 0x8000000000000000;
269}
270*/
271
272/// Aligns a type to a given number of bytes.
273#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
274pub struct Aligned<T, const N: usize>
275where
276    Align<N>: Alignment,
277{
278    /// Aligner.
279    align: Align<N>,
280
281    /// Aligned value.
282    inner: T,
283}
284impl<T, const N: usize> Aligned<T, N>
285where
286    Align<N>: Alignment,
287{
288    /// Create new aligned value.
289    pub const fn new(inner: T) -> Aligned<T, N> {
290        Aligned {
291            align: Align([]),
292            inner,
293        }
294    }
295
296    /// Return unaligned value.
297    pub const fn into_inner(self) -> T {
298        // SAFETY: We immediately forget `self` to avoid double-drop.
299        let inner = unsafe { mem::transmute_copy(&self) };
300        mem::forget(self);
301        inner
302    }
303}
304impl<T, const N: usize> ops::Deref for Aligned<T, N>
305where
306    Align<N>: Alignment,
307{
308    type Target = T;
309
310    #[inline]
311    fn deref(&self) -> &T {
312        &self.inner
313    }
314}
315impl<T, const N: usize> ops::DerefMut for Aligned<T, N>
316where
317    Align<N>: Alignment,
318{
319    #[inline]
320    fn deref_mut(&mut self) -> &mut T {
321        &mut self.inner
322    }
323}
324
325/// Opt-in guarantee that a type does not contain any padding bytes.
326///
327/// Note that this does not mean that all values of a type have to be
328/// possible, just that when the type is copied, all of its bytes are copied.
329///
330/// This is required, for the moment, to ensure that [`Misaligned`] works
331/// correctly. Ideally, it will not be required in the future.
332#[cfg_attr(feature = "nightly", marker)]
333pub trait Unpadded {}
334impl<T: Unpadded, const N: usize> Unpadded for [T; N] {}
335impl<T> Unpadded for PhantomData<T> {}
336impl<const N: usize> Unpadded for Align<N>
337where
338    Align<N>: Alignment {}
339impl<const N: usize> Unpadded for Padding<N>
340where
341    Align<N>: Alignment {}
342
343#[cfg(feature = "nightly")]
344impl<T> Unpadded for [T; 0] {}
345
346/// Implements [`Unpadded`] for a type.
347macro_rules! impl_unpadded {
348    ($($t:ty),* $(,)?) => {
349        $(
350            impl Unpadded for $t {}
351        )*
352    }
353}
354impl_unpadded! {
355    bool,
356    u8,
357    u16,
358    u32,
359    u64,
360    u128,
361    usize,
362    i8,
363    i16,
364    i32,
365    i64,
366    i128,
367    isize,
368    char,
369    NonZero<u8>,
370    NonZero<u16>,
371    NonZero<u32>,
372    NonZero<u64>,
373    NonZero<u128>,
374    NonZero<usize>,
375    NonZero<i8>,
376    NonZero<i16>,
377    NonZero<i32>,
378    NonZero<i64>,
379    NonZero<i128>,
380    NonZero<isize>,
381    NonZero<char>,
382    (),
383}
384
385/// Padding for [`Misaligned`].
386///
387/// This has to be a union to ensure that, if `T` is more aligned than `N`,
388/// we still have non-padding bytes to write `T` in.
389#[repr(C)]
390union MisalignedPadding<T, const N: usize>
391where
392    Align<N>: Alignment,
393{
394    /// Padding.
395    padding: Padding<N>,
396
397    /// Value.
398    value: mem::ManuallyDrop<T>,
399}
400
401/// Ensures that a type is *not* aligned to a given number of bytes.
402///
403/// `T` will have its own alignment, but all higher alignments up to `N` will
404/// not be satisfied. This involves padding of at least `N` bytes, but probably
405/// more.
406#[repr(C)]
407pub struct Misaligned<T: Unpadded, const N: usize>
408where
409    Align<N>: Alignment,
410{
411    /// Aligner.
412    align: Align<N>,
413
414    /// Padding.
415    padding: mem::MaybeUninit<MisalignedPadding<T, N>>,
416
417    /// Value.
418    value: mem::MaybeUninit<T>,
419}
420impl<T: Unpadded, const N: usize> Misaligned<T, N>
421where
422    Align<N>: Alignment,
423{
424    /// Write offset of value.
425    pub(crate) const OFFSET: usize = mem::offset_of!(Misaligned<T, N>, value) - align_of::<T>();
426
427    /// Create new aligned value.
428    pub const fn new(inner: T) -> Misaligned<T, N> {
429        let mut base: Self = Misaligned {
430            align: Align([]),
431            padding: mem::MaybeUninit::uninit(),
432            value: mem::MaybeUninit::uninit(),
433        };
434        base.as_mut_uninit().write(inner);
435        base
436    }
437
438    /// Get maybe-uninit value inside.
439    const fn as_uninit(&self) -> &mem::MaybeUninit<T> {
440        // SAFETY: All bytes inside this range are maybe-uninit,
441        // and the.
442        unsafe {
443            &*ptr::from_ref(self)
444                .byte_add(Self::OFFSET)
445                .cast::<T>()
446                .cast::<mem::MaybeUninit<T>>()
447        }
448    }
449
450    /// Get maybe-uninit value inside.
451    const fn as_mut_uninit(&mut self) -> &mut mem::MaybeUninit<T> {
452        // SAFETY: All bytes inside this range are maybe-uninit.
453        unsafe {
454            &mut *ptr::from_mut(self)
455                .byte_add(Self::OFFSET)
456                .cast::<T>()
457                .cast::<mem::MaybeUninit<T>>()
458        }
459    }
460
461    /// Return unaligned value.
462    pub const fn into_inner(self) -> T {
463        // SAFETY: We immediately forget `self` to avoid double-drop.
464        let inner = unsafe { self.as_uninit().assume_init_read() };
465        mem::forget(self);
466        inner
467    }
468}
469impl<T: Unpadded, const N: usize> ops::Deref for Misaligned<T, N>
470where
471    Align<N>: Alignment,
472{
473    type Target = T;
474
475    #[inline]
476    fn deref(&self) -> &T {
477        // SAFETY: We always initialize T.
478        unsafe { self.as_uninit().assume_init_ref() }
479    }
480}
481impl<T: Unpadded, const N: usize> ops::DerefMut for Misaligned<T, N>
482where
483    Align<N>: Alignment,
484{
485    #[inline]
486    fn deref_mut(&mut self) -> &mut T {
487        // SAFETY: We always initialize T.
488        unsafe { self.as_mut_uninit().assume_init_mut() }
489    }
490}
491impl<T: Unpadded, const N: usize> Drop for Misaligned<T, N>
492where
493    Align<N>: Alignment,
494{
495    #[inline]
496    fn drop(&mut self) {
497        // SAFETY: We always initialize T.
498        unsafe { self.as_mut_uninit().assume_init_drop() }
499    }
500}
501
502/// Trivial implementations for traits.
503#[cfg_attr(any(feature = "nightly", coverage_nightly), coverage(off))]
504#[cfg_attr(test, mutants::skip)]
505mod trivial_impls {
506    use core::{cmp, fmt, hash, mem};
507
508    use crate::core::{Align, Aligned, Alignment, Misaligned, Padding, Unpadded};
509
510    impl<const N: usize> PartialEq for Align<N>
511    where
512        Align<N>: Alignment,
513    {
514        #[inline]
515        fn eq(&self, _: &Self) -> bool {
516            true
517        }
518    }
519    impl<const N: usize> Eq for Align<N> where Align<N>: Alignment {}
520    #[expect(clippy::non_canonical_partial_ord_impl)]
521    impl<const N: usize> PartialOrd for Align<N>
522    where
523        Align<N>: Alignment,
524    {
525        #[inline]
526        fn partial_cmp(&self, _: &Align<N>) -> Option<cmp::Ordering> {
527            Some(cmp::Ordering::Equal)
528        }
529    }
530    impl<const N: usize> Ord for Align<N>
531    where
532        Align<N>: Alignment,
533    {
534        #[inline]
535        fn cmp(&self, _: &Align<N>) -> cmp::Ordering {
536            cmp::Ordering::Equal
537        }
538    }
539    impl<const N: usize> hash::Hash for Align<N>
540    where
541        Align<N>: Alignment,
542    {
543        #[inline]
544        fn hash<H: hash::Hasher>(&self, _: &mut H) {}
545    }
546    impl<const N: usize> Default for Align<N>
547    where
548        Align<N>: Alignment,
549    {
550        #[inline]
551        fn default() -> Align<N> {
552            Align([])
553        }
554    }
555
556    impl<const N: usize> PartialEq for Padding<N>
557    where
558        Align<N>: Alignment,
559    {
560        #[inline]
561        fn eq(&self, _: &Self) -> bool {
562            true
563        }
564    }
565    impl<const N: usize> Eq for Padding<N> where Align<N>: Alignment {}
566    #[expect(clippy::non_canonical_partial_ord_impl)]
567    impl<const N: usize> PartialOrd for Padding<N>
568    where
569        Align<N>: Alignment,
570    {
571        #[inline]
572        fn partial_cmp(&self, _: &Padding<N>) -> Option<cmp::Ordering> {
573            Some(cmp::Ordering::Equal)
574        }
575    }
576    impl<const N: usize> Ord for Padding<N>
577    where
578        Align<N>: Alignment,
579    {
580        #[inline]
581        fn cmp(&self, _: &Padding<N>) -> cmp::Ordering {
582            cmp::Ordering::Equal
583        }
584    }
585    impl<const N: usize> hash::Hash for Padding<N>
586    where
587        Align<N>: Alignment,
588    {
589        #[inline]
590        fn hash<H: hash::Hasher>(&self, _: &mut H) {}
591    }
592    impl<const N: usize> Default for Padding<N>
593    where
594        Align<N>: Alignment,
595    {
596        #[inline]
597        fn default() -> Padding<N> {
598            Padding(mem::MaybeUninit::uninit())
599        }
600    }
601
602    impl<T: Unpadded + Clone, const N: usize> Clone for Misaligned<T, N>
603    where
604        Align<N>: Alignment,
605    {
606        #[inline]
607        fn clone(&self) -> Misaligned<T, N> {
608            Misaligned::new((**self).clone())
609        }
610    }
611    // can't conditionally implement destructor, so, can't be Copy
612    // impl<T: Copy, const N: usize> Copy for Misaligned<T, N> where Align<N>: Alignment {}
613    impl<T: Unpadded + PartialEq, const N: usize> PartialEq for Misaligned<T, N>
614    where
615        Align<N>: Alignment,
616    {
617        #[inline]
618        fn eq(&self, other: &Misaligned<T, N>) -> bool {
619            **self == **other
620        }
621    }
622    impl<T: Unpadded + Eq, const N: usize> Eq for Misaligned<T, N> where Align<N>: Alignment {}
623    impl<T: Unpadded + PartialOrd, const N: usize> PartialOrd for Misaligned<T, N>
624    where
625        Align<N>: Alignment,
626    {
627        #[inline]
628        fn partial_cmp(&self, other: &Misaligned<T, N>) -> Option<cmp::Ordering> {
629            PartialOrd::partial_cmp(&**self, &**other)
630        }
631    }
632    impl<T: Unpadded + Ord, const N: usize> Ord for Misaligned<T, N>
633    where
634        Align<N>: Alignment,
635    {
636        #[inline]
637        fn cmp(&self, other: &Misaligned<T, N>) -> cmp::Ordering {
638            Ord::cmp(&**self, &**other)
639        }
640    }
641    impl<T: Unpadded + hash::Hash, const N: usize> hash::Hash for Misaligned<T, N>
642    where
643        Align<N>: Alignment,
644    {
645        #[inline]
646        fn hash<H: hash::Hasher>(&self, state: &mut H) {
647            hash::Hash::hash(&**self, state);
648        }
649    }
650    impl<T: Unpadded + Default, const N: usize> Default for Misaligned<T, N>
651    where
652        Align<N>: Alignment,
653    {
654        #[inline]
655        fn default() -> Misaligned<T, N> {
656            Misaligned::new(Default::default())
657        }
658    }
659
660    /// Implements formatting traits for [`Aligned`].
661    macro_rules! fmt_impl_aligned {
662        (
663            $($trait:ident),* $(,)?
664        ) => {
665            $(
666                impl<T: fmt::$trait, const N: usize> fmt::$trait for Aligned<T, N>
667                where
668                    Align<N>: Alignment,
669                {
670                    #[inline]
671                    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
672                        fmt::$trait::fmt(&**self, f)
673                    }
674                }
675            )*
676        }
677    }
678    /// Implements formatting traits for [`Misaligned`].
679    macro_rules! fmt_impl_misaligned {
680        ($($trait:ident),* $(,)?) => {
681            $(
682                impl<T: Unpadded + fmt::$trait, const N: usize> fmt::$trait for Misaligned<T, N>
683                where
684                    Align<N>: Alignment,
685                {
686                    #[inline]
687                    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
688                        fmt::$trait::fmt(&**self, f)
689                    }
690                }
691            )*
692        }
693    }
694    fmt_impl_aligned! {
695        Binary,
696        Debug,
697        Display,
698        LowerExp,
699        LowerHex,
700        Octal,
701        Pointer,
702        UpperExp,
703        UpperHex,
704    }
705    fmt_impl_misaligned! {
706        Binary,
707        Debug,
708        Display,
709        LowerExp,
710        LowerHex,
711        Octal,
712        Pointer,
713        UpperExp,
714        UpperHex,
715    }
716}
717
718#[cfg(test)]
719mod tests {
720    use core::{
721        mem::align_of,
722        sync::atomic::{AtomicUsize, Ordering},
723    };
724
725    use crate::core::{Align, Alignment, Padding, Unpadded, aligned, misaligned};
726
727    macro_rules! check_aligned {
728        ($t:ty, $align:literal) => {
729            let mut val = aligned::<$t, $align>(0);
730            *val = 1;
731            assert_eq!(*val, 1);
732            assert_eq!(val.into_inner(), 1);
733
734            assert_eq!(
735                (&raw const *aligned::<$t, $align>(0)).align_offset($align),
736                0,
737                concat!(stringify!($t), " was not ", stringify!($align), "-aligned"),
738            );
739        };
740    }
741
742    macro_rules! check_misaligned {
743        ($value:literal: $t:ty, $align:literal) => {
744            let val = misaligned::<$t, $align>($value);
745            assert_eq!(
746                *val, $value,
747                concat!(
748                    stringify!($t),
749                    " when ",
750                    stringify!($align),
751                    "-misaligned has incorrect value"
752                ),
753            );
754            assert_eq!(
755                val.into_inner(), $value,
756                concat!(
757                    stringify!($t),
758                    " when ",
759                    stringify!($align),
760                    "-misaligned has incorrect value"
761                ),
762            );
763            let mut val = misaligned::<$t, $align>(0);
764            *val = $value;
765            assert_eq!(
766                *val, $value,
767                concat!(
768                    stringify!($t),
769                    " when ",
770                    stringify!($align),
771                    "-misaligned has incorrect value"
772                ),
773            );
774            let mut power = align_of::<$t>();
775            loop {
776                power <<= 1;
777                if power >= $align {
778                    break;
779                }
780                assert_ne!(
781                    (&raw const *val).align_offset(power),
782                    0,
783                    concat!(
784                        stringify!($t),
785                        " when ",
786                        stringify!($align),
787                        "-misaligned was {}-aligned"
788                    ),
789                    power,
790                );
791            }
792        };
793    }
794
795    // required to avoid stack overflow
796    fn box_padding<const N: usize>() -> Box<Padding<N>>
797    where
798        Align<N>: Alignment,
799    {
800        // SAFETY: This is already uninitialized, so, it's okay.
801        unsafe { Box::new_uninit().assume_init() }
802    }
803
804    // required to avoid stack overflow
805    fn box_align<const N: usize>() -> Box<Align<N>>
806    where
807        Align<N>: Alignment,
808    {
809        // SAFETY: This is a ZST, so, it's okay.
810        unsafe { Box::new_uninit().assume_init() }
811    }
812
813    #[test]
814    fn test_debug_padding() {
815        assert_eq!(
816            format!("{:?}", box_padding::<{ 1 << 0 }>()),
817            "Padding<{1 << 0}>"
818        );
819        assert_eq!(
820            format!("{:?}", box_padding::<{ 1 << 9 }>()),
821            "Padding<{1 << 9}>"
822        );
823        assert_eq!(
824            format!("{:?}", box_padding::<{ 1 << 10 }>()),
825            "Padding<{1 << 10}>"
826        );
827        assert_eq!(
828            format!("{:?}", box_padding::<{ 1 << 11 }>()),
829            "Padding<{1 << 11}>"
830        );
831        assert_eq!(
832            format!("{:?}", box_padding::<{ 1 << 21 }>()),
833            "Padding<{1 << 21}>"
834        );
835    }
836
837    #[test]
838    fn test_debug_align() {
839        assert_eq!(
840            format!("{:?}", box_align::<{ 1 << 0 }>()),
841            "Align<{1 << 0}>"
842        );
843        assert_eq!(
844            format!("{:?}", box_align::<{ 1 << 9 }>()),
845            "Align<{1 << 9}>"
846        );
847        assert_eq!(
848            format!("{:?}", box_align::<{ 1 << 10 }>()),
849            "Align<{1 << 10}>"
850        );
851        assert_eq!(
852            format!("{:?}", box_align::<{ 1 << 11 }>()),
853            "Align<{1 << 11}>"
854        );
855        assert_eq!(
856            format!("{:?}", box_align::<{ 1 << 21 }>()),
857            "Align<{1 << 21}>"
858        );
859    }
860
861    #[test]
862    fn test_underaligned() {
863        check_aligned!(u8, 1);
864        check_aligned!(u16, 1);
865        check_aligned!(u16, 2);
866        check_aligned!(u32, 1);
867        check_aligned!(u32, 2);
868        check_aligned!(u32, 4);
869        check_aligned!(u64, 1);
870        check_aligned!(u64, 2);
871        check_aligned!(u64, 4);
872        check_aligned!(u64, 8);
873        check_aligned!(u128, 1);
874        check_aligned!(u128, 2);
875        check_aligned!(u128, 4);
876        check_aligned!(u128, 8);
877        check_aligned!(u128, 16);
878    }
879
880    #[test]
881    fn test_overaligned() {
882        check_aligned!(u8, 2);
883        check_aligned!(u8, 4);
884        check_aligned!(u8, 8);
885        check_aligned!(u8, 16);
886        check_aligned!(u8, 32);
887        check_aligned!(u8, 64);
888        check_aligned!(u8, 128);
889        check_aligned!(u8, 256);
890        check_aligned!(u8, 512);
891        check_aligned!(u16, 4);
892        check_aligned!(u16, 8);
893        check_aligned!(u16, 16);
894        check_aligned!(u16, 32);
895        check_aligned!(u16, 64);
896        check_aligned!(u16, 128);
897        check_aligned!(u16, 256);
898        check_aligned!(u16, 512);
899        check_aligned!(u32, 8);
900        check_aligned!(u32, 16);
901        check_aligned!(u32, 32);
902        check_aligned!(u32, 64);
903        check_aligned!(u32, 128);
904        check_aligned!(u32, 256);
905        check_aligned!(u32, 512);
906        check_aligned!(u64, 16);
907        check_aligned!(u64, 32);
908        check_aligned!(u64, 64);
909        check_aligned!(u64, 128);
910        check_aligned!(u64, 256);
911        check_aligned!(u64, 512);
912        check_aligned!(u128, 32);
913        check_aligned!(u128, 64);
914        check_aligned!(u128, 128);
915        check_aligned!(u128, 256);
916        check_aligned!(u128, 512);
917    }
918
919    #[test]
920    fn test_padding_size() {
921        assert_eq!(size_of::<Padding<1>>(), 1);
922        assert_eq!(size_of::<Padding<2>>(), 2);
923        assert_eq!(size_of::<Padding<4>>(), 4);
924        assert_eq!(size_of::<Padding<8>>(), 8);
925        assert_eq!(size_of::<Padding<16>>(), 16);
926        assert_eq!(size_of::<Padding<32>>(), 32);
927        assert_eq!(size_of::<Padding<64>>(), 64);
928        assert_eq!(size_of::<Padding<128>>(), 128);
929        assert_eq!(size_of::<Padding<256>>(), 256);
930        assert_eq!(size_of::<Padding<512>>(), 512);
931    }
932
933    #[test]
934    fn test_not_misaligned() {
935        check_misaligned!(0x11: u8, 1);
936        check_misaligned!(0x1122: u16, 1);
937        check_misaligned!(0x1122: u16, 2);
938        check_misaligned!(0x1122: u32, 1);
939        check_misaligned!(0x11223344: u32, 2);
940        check_misaligned!(0x11223344: u32, 4);
941        check_misaligned!(0x1122334455667788: u64, 1);
942        check_misaligned!(0x1122334455667788: u64, 2);
943        check_misaligned!(0x1122334455667788: u64, 4);
944        check_misaligned!(0x1122334455667788: u64, 8);
945        check_misaligned!(0x11223344556677887766554433221100: u128, 1);
946        check_misaligned!(0x11223344556677887766554433221100: u128, 2);
947        check_misaligned!(0x11223344556677887766554433221100: u128, 4);
948        check_misaligned!(0x11223344556677887766554433221100: u128, 8);
949        check_misaligned!(0x11223344556677887766554433221100: u128, 16);
950    }
951
952    #[test]
953    fn test_misaligned() {
954        check_misaligned!(0x11: u8, 2);
955        check_misaligned!(0x11: u8, 4);
956        check_misaligned!(0x11: u8, 8);
957        check_misaligned!(0x11: u8, 16);
958        check_misaligned!(0x11: u8, 32);
959        check_misaligned!(0x11: u8, 64);
960        check_misaligned!(0x11: u8, 128);
961        check_misaligned!(0x11: u8, 256);
962        check_misaligned!(0x11: u8, 512);
963        check_misaligned!(0x1122: u16, 4);
964        check_misaligned!(0x1122: u16, 8);
965        check_misaligned!(0x1122: u16, 16);
966        check_misaligned!(0x1122: u16, 32);
967        check_misaligned!(0x1122: u16, 64);
968        check_misaligned!(0x1122: u16, 128);
969        check_misaligned!(0x1122: u16, 256);
970        check_misaligned!(0x1122: u16, 512);
971        check_misaligned!(0x11223344: u32, 8);
972        check_misaligned!(0x11223344: u32, 16);
973        check_misaligned!(0x11223344: u32, 32);
974        check_misaligned!(0x11223344: u32, 64);
975        check_misaligned!(0x11223344: u32, 128);
976        check_misaligned!(0x11223344: u32, 256);
977        check_misaligned!(0x11223344: u32, 512);
978        check_misaligned!(0x1122334455667788: u64, 16);
979        check_misaligned!(0x1122334455667788: u64, 32);
980        check_misaligned!(0x1122334455667788: u64, 64);
981        check_misaligned!(0x1122334455667788: u64, 128);
982        check_misaligned!(0x1122334455667788: u64, 256);
983        check_misaligned!(0x1122334455667788: u64, 512);
984        check_misaligned!(0x11223344556677887766554433221100: u128, 32);
985        check_misaligned!(0x11223344556677887766554433221100: u128, 64);
986        check_misaligned!(0x11223344556677887766554433221100: u128, 128);
987        check_misaligned!(0x11223344556677887766554433221100: u128, 256);
988        check_misaligned!(0x11223344556677887766554433221100: u128, 512);
989    }
990
991    // FIXME: padding byte hell
992    // https://github.com/rust-lang/unsafe-code-guidelines/issues/599
993    fn try_misaligned_drop<const N: usize>(counter: &AtomicUsize) {
994        struct MyTest<'a>(usize, &'a AtomicUsize);
995        impl Unpadded for MyTest<'_> {}
996        impl Drop for MyTest<'_> {
997            fn drop(&mut self) {
998                if self.0 == 0x1122 {
999                    self.1.fetch_add(1, Ordering::Relaxed);
1000                }
1001            }
1002        }
1003        let _ = misaligned::<MyTest, 1>(MyTest(0x1122, counter));
1004
1005        // to test mismatched branch
1006        let _ = misaligned::<MyTest, 1>(MyTest(0, counter));
1007    }
1008
1009    #[test]
1010    fn test_misaligned_drop() {
1011        let counter = AtomicUsize::new(0);
1012        try_misaligned_drop::<1>(&counter);
1013        try_misaligned_drop::<2>(&counter);
1014        try_misaligned_drop::<4>(&counter);
1015        try_misaligned_drop::<8>(&counter);
1016        try_misaligned_drop::<16>(&counter);
1017        assert_eq!(counter.load(Ordering::Relaxed), 5);
1018    }
1019}