1use core::{fmt, marker::PhantomData, mem, num::NonZero, ops, ptr};
5
6pub const fn align<const N: usize>() -> Align<N>
14where
15 Align<N>: Alignment,
16{
17 Align::new()
18}
19
20pub const fn padding<const N: usize>() -> Padding<N>
28where
29 Align<N>: Alignment,
30{
31 Padding::new()
32}
33
34pub const fn aligned<T, const N: usize>(value: T) -> Aligned<T, N>
42where
43 Align<N>: Alignment,
44{
45 Aligned::new(value)
46}
47
48pub 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#[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 #[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 let s = unsafe { str::from_utf8_unchecked(&buf[..len]) };
105 f.pad(s)
106 }
107}
108
109#[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 #[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 let s = unsafe { str::from_utf8_unchecked(&buf[..len]) };
150 f.pad(s)
151 }
152}
153
154mod sealed {
156 pub trait Sealed {}
158}
159
160pub trait Alignment: sealed::Sealed {
166 #[doc(hidden)]
168 type Align: 'static + Copy;
169
170 #[doc(hidden)]
172 type Padding: 'static + Copy;
173}
174
175macro_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 }
234#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
274pub struct Aligned<T, const N: usize>
275where
276 Align<N>: Alignment,
277{
278 align: Align<N>,
280
281 inner: T,
283}
284impl<T, const N: usize> Aligned<T, N>
285where
286 Align<N>: Alignment,
287{
288 pub const fn new(inner: T) -> Aligned<T, N> {
290 Aligned {
291 align: Align([]),
292 inner,
293 }
294 }
295
296 pub const fn into_inner(self) -> T {
298 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#[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
346macro_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#[repr(C)]
390union MisalignedPadding<T, const N: usize>
391where
392 Align<N>: Alignment,
393{
394 padding: Padding<N>,
396
397 value: mem::ManuallyDrop<T>,
399}
400
401#[repr(C)]
407pub struct Misaligned<T: Unpadded, const N: usize>
408where
409 Align<N>: Alignment,
410{
411 align: Align<N>,
413
414 padding: mem::MaybeUninit<MisalignedPadding<T, N>>,
416
417 value: mem::MaybeUninit<T>,
419}
420impl<T: Unpadded, const N: usize> Misaligned<T, N>
421where
422 Align<N>: Alignment,
423{
424 pub(crate) const OFFSET: usize = mem::offset_of!(Misaligned<T, N>, value) - align_of::<T>();
426
427 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 const fn as_uninit(&self) -> &mem::MaybeUninit<T> {
440 unsafe {
443 &*ptr::from_ref(self)
444 .byte_add(Self::OFFSET)
445 .cast::<T>()
446 .cast::<mem::MaybeUninit<T>>()
447 }
448 }
449
450 const fn as_mut_uninit(&mut self) -> &mut mem::MaybeUninit<T> {
452 unsafe {
454 &mut *ptr::from_mut(self)
455 .byte_add(Self::OFFSET)
456 .cast::<T>()
457 .cast::<mem::MaybeUninit<T>>()
458 }
459 }
460
461 pub const fn into_inner(self) -> T {
463 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 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 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 unsafe { self.as_mut_uninit().assume_init_drop() }
499 }
500}
501
502#[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 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 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 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 fn box_padding<const N: usize>() -> Box<Padding<N>>
797 where
798 Align<N>: Alignment,
799 {
800 unsafe { Box::new_uninit().assume_init() }
802 }
803
804 fn box_align<const N: usize>() -> Box<Align<N>>
806 where
807 Align<N>: Alignment,
808 {
809 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 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 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}