1use std::{marker::PhantomData, mem::ManuallyDrop};
4
5pub unsafe trait InlineStorage {}
16
17macro_rules! impl_for_arrays {
18 ( ty=$ty:ty , len[ $($len:expr),* $(,)* ] ) => (
19 $(
20 unsafe impl InlineStorage for [$ty;$len] {}
21 )*
22 )
23}
24
25impl_for_arrays! {
26 ty=u8,
27 len[
28 0,1,2,3,4,5,6,7,8,9,
29 10,11,12,13,14,15,16,17,18,19,
30 20,21,22,23,24,25,26,27,28,29,
31 30,31,32,33,34,35,36,37,38,39,
32 40,41,42,43,44,45,46,47,48,49,
33 50,51,52,53,54,55,56,57,58,59,
34 60,61,62,63,64,
35 ]
36}
37
38impl_for_arrays! {
39 ty=u32,
40 len[
41 0,1,2,3,4,5,6,7,8,9,
42 10,11,12,13,14,15,16,17,18,19,
43 20,21,22,23,24,25,26,27,28,29,
44 30,31,32,33,34,35,36,37,38,39,
45 40,41,42,43,44,45,46,47,48,
46 ]
47}
48
49impl_for_arrays! {
50 ty=u64,
51 len[
52 0,1,2,3,4,5,6,7,8,9,
53 10,11,12,13,14,15,16,17,18,19,
54 20,21,22,23,24,
55 ]
56}
57
58impl_for_arrays! {
59 ty=usize,
60 len[
61 0,1,2,3,4,5,6,7,8,9,
62 10,11,12,13,14,15,16,17,18,19,
63 20,21,22,23,24,25,26,27,28,29,
64 30,31,32,33,34,35,36,37,38,39,
65 40,41,42,43,44,45,46,47,48,
66 ]
67}
68
69mod private {
70 use super::*;
71 pub struct Private<T, const ALIGNMENT: usize>(pub(super) PhantomData<T>);
72}
73use private::Private;
74
75pub trait AlignerFor<const ALIGNMENT: usize>: Sized {
77 #[doc(hidden)]
79 const __PRIVATE_12350662443733019984: Private<Self, ALIGNMENT>;
80
81 type Aligner;
83}
84
85pub type GetAlignerFor<T, const ALIGNMENT: usize> = <T as AlignerFor<ALIGNMENT>>::Aligner;
87
88macro_rules! declare_alignments {
89 (
90 $(( $aligner:ident, $alignment:expr),)*
91 ) => (
92 $(
93 #[doc = concat!(
94 "Aligns its contents to an address at a multiple of ",
95 $alignment,
96 " bytes."
97 )]
98 #[derive(StableAbi, Debug, PartialEq, Eq, Copy, Clone)]
99 #[repr(C)]
100 #[repr(align($alignment))]
101 pub struct $aligner<Inline>(pub Inline);
102
103 unsafe impl<Inline> InlineStorage for $aligner<Inline>
104 where
105 Inline: InlineStorage,
106 {}
107
108 impl<T> AlignerFor<$alignment> for T {
109 #[doc(hidden)]
110 const __PRIVATE_12350662443733019984: Private<T, $alignment> = Private(PhantomData);
111
112 type Aligner = $aligner<T>;
113 }
114 )*
115 )
116}
117
118pub mod alignment {
120 use super::*;
121
122 declare_alignments! {
131 (AlignTo1, 1),
132 (AlignTo2, 2),
133 (AlignTo4, 4),
134 (AlignTo8, 8),
135 (AlignTo16, 16),
136 (AlignTo32, 32),
137 (AlignTo64, 64),
138 (AlignTo128, 128),
139 (AlignTo256, 256),
140 (AlignTo512, 512),
141 (AlignTo1024, 1024),
142 (AlignTo2048, 2048),
143 (AlignTo4096, 4096),
144 (AlignTo8192, 8192),
145 (AlignTo16384, 16384),
146 (AlignTo32768, 32768),
147 }
148
149 #[repr(C)]
152 #[derive(Debug, PartialEq, Eq, Copy, Clone)]
153 #[cfg_attr(target_pointer_width = "128", repr(C, align(16)))]
154 #[cfg_attr(target_pointer_width = "64", repr(C, align(8)))]
155 #[cfg_attr(target_pointer_width = "32", repr(C, align(4)))]
156 #[cfg_attr(target_pointer_width = "16", repr(C, align(2)))]
157 pub struct AlignToUsize<Inline>(pub Inline);
158
159 unsafe impl<Inline> InlineStorage for AlignToUsize<Inline> where Inline: InlineStorage {}
160}
161
162#[repr(transparent)]
165pub(crate) struct ScratchSpace<T, Inline> {
166 #[allow(dead_code)]
167 inner: ScratchSpaceInner<T, Inline>,
168}
169
170#[repr(C)]
171union ScratchSpaceInner<T, Inline> {
172 value: ManuallyDrop<T>,
173 storage: ManuallyDrop<Inline>,
174 uninit: (),
175}
176
177impl<T, Inline> ScratchSpace<T, Inline> {
181 #[inline]
182 #[allow(dead_code)]
183 #[track_caller]
184 pub(crate) const fn uninit() -> Self {
185 Self::assert_fits_within_storage();
186 Self {
187 inner: ScratchSpaceInner { uninit: () },
188 }
189 }
190
191 #[inline]
192 #[allow(dead_code)]
193 #[track_caller]
194 pub(crate) const fn new(value: T) -> Self {
195 Self::assert_fits_within_storage();
196 Self {
197 inner: ScratchSpaceInner {
198 value: ManuallyDrop::new(value),
199 },
200 }
201 }
202
203 #[track_caller]
205 const fn assert_fits_within_storage() {
206 use crate::nonexhaustive_enum::AssertCsArgs;
207
208 crate::nonexhaustive_enum::assert_correct_storage::<T, Inline>(AssertCsArgs::UNKNOWN)
209 }
210}