1#![allow(clippy::enum_clike_unportable_variant)]
2
3#[cfg(not(feature = "ferrocene_certified"))]
4use crate::num::NonZero;
5#[cfg(not(feature = "ferrocene_certified"))]
6use crate::ub_checks::assert_unsafe_precondition;
7#[cfg(not(feature = "ferrocene_certified"))]
8use crate::{cmp, fmt, hash, mem, num};
9#[cfg(feature = "ferrocene_certified")]
11use crate::{mem, ub_checks::assert_unsafe_precondition};
12
13#[unstable(feature = "ptr_alignment_type", issue = "102070")]
19#[cfg_attr(not(feature = "ferrocene_certified"), derive(Copy, Clone, PartialEq, Eq))]
20#[cfg_attr(feature = "ferrocene_certified", derive(Copy, Clone))]
21#[repr(transparent)]
22pub struct Alignment(AlignmentEnum);
23
24#[cfg(not(feature = "ferrocene_certified"))]
26const _: () = assert!(size_of::<Alignment>() == size_of::<usize>());
27#[cfg(not(feature = "ferrocene_certified"))]
28const _: () = assert!(align_of::<Alignment>() == align_of::<usize>());
29
30#[cfg(not(feature = "ferrocene_certified"))]
31fn _alignment_can_be_structurally_matched(a: Alignment) -> bool {
32 matches!(a, Alignment::MIN)
33}
34
35impl Alignment {
36 #[unstable(feature = "ptr_alignment_type", issue = "102070")]
49 #[cfg(not(feature = "ferrocene_certified"))]
50 pub const MIN: Self = Self(AlignmentEnum::_Align1Shl0);
51
52 #[unstable(feature = "ptr_alignment_type", issue = "102070")]
57 #[inline]
58 #[must_use]
59 #[cfg(not(feature = "ferrocene_certified"))]
60 pub const fn of<T>() -> Self {
61 const { Alignment::new(align_of::<T>()).unwrap() }
63 }
64
65 #[unstable(feature = "ptr_alignment_type", issue = "102070")]
70 #[inline]
71 pub const fn new(align: usize) -> Option<Self> {
72 if align.is_power_of_two() {
73 Some(unsafe { Self::new_unchecked(align) })
75 } else {
76 None
77 }
78 }
79
80 #[unstable(feature = "ptr_alignment_type", issue = "102070")]
89 #[inline]
90 #[track_caller]
91 pub const unsafe fn new_unchecked(align: usize) -> Self {
92 assert_unsafe_precondition!(
93 check_language_ub,
94 "Alignment::new_unchecked requires a power of two",
95 (align: usize = align) => align.is_power_of_two()
96 );
97
98 unsafe { mem::transmute::<usize, Alignment>(align) }
101 }
102
103 #[unstable(feature = "ptr_alignment_type", issue = "102070")]
105 #[inline]
106 pub const fn as_usize(self) -> usize {
107 self.0 as usize
108 }
109
110 #[unstable(feature = "ptr_alignment_type", issue = "102070")]
112 #[inline]
113 #[cfg(not(feature = "ferrocene_certified"))]
114 pub const fn as_nonzero(self) -> NonZero<usize> {
115 unsafe { mem::transmute::<Alignment, NonZero<usize>>(self) }
122 }
123
124 #[unstable(feature = "ptr_alignment_type", issue = "102070")]
138 #[inline]
139 #[cfg(not(feature = "ferrocene_certified"))]
140 pub const fn log2(self) -> u32 {
141 self.as_nonzero().trailing_zeros()
142 }
143
144 #[unstable(feature = "ptr_alignment_type", issue = "102070")]
168 #[inline]
169 #[cfg(not(feature = "ferrocene_certified"))]
170 pub const fn mask(self) -> usize {
171 !(unsafe { self.as_usize().unchecked_sub(1) })
173 }
174
175 #[cfg(not(feature = "ferrocene_certified"))]
177 pub(crate) const fn max(a: Self, b: Self) -> Self {
178 if a.as_usize() > b.as_usize() { a } else { b }
179 }
180}
181
182#[unstable(feature = "ptr_alignment_type", issue = "102070")]
183#[cfg(not(feature = "ferrocene_certified"))]
184impl fmt::Debug for Alignment {
185 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
186 write!(f, "{:?} (1 << {:?})", self.as_nonzero(), self.log2())
187 }
188}
189
190#[unstable(feature = "ptr_alignment_type", issue = "102070")]
191#[cfg(not(feature = "ferrocene_certified"))]
192impl TryFrom<NonZero<usize>> for Alignment {
193 type Error = num::TryFromIntError;
194
195 #[inline]
196 fn try_from(align: NonZero<usize>) -> Result<Alignment, Self::Error> {
197 align.get().try_into()
198 }
199}
200
201#[unstable(feature = "ptr_alignment_type", issue = "102070")]
202#[cfg(not(feature = "ferrocene_certified"))]
203impl TryFrom<usize> for Alignment {
204 type Error = num::TryFromIntError;
205
206 #[inline]
207 fn try_from(align: usize) -> Result<Alignment, Self::Error> {
208 Self::new(align).ok_or(num::TryFromIntError(()))
209 }
210}
211
212#[unstable(feature = "ptr_alignment_type", issue = "102070")]
213#[rustc_const_unstable(feature = "const_try", issue = "74935")]
214#[cfg(not(feature = "ferrocene_certified"))]
215impl const From<Alignment> for NonZero<usize> {
216 #[inline]
217 fn from(align: Alignment) -> NonZero<usize> {
218 align.as_nonzero()
219 }
220}
221
222#[unstable(feature = "ptr_alignment_type", issue = "102070")]
223#[rustc_const_unstable(feature = "const_try", issue = "74935")]
224#[cfg(not(feature = "ferrocene_certified"))]
225impl const From<Alignment> for usize {
226 #[inline]
227 fn from(align: Alignment) -> usize {
228 align.as_usize()
229 }
230}
231
232#[unstable(feature = "ptr_alignment_type", issue = "102070")]
233#[cfg(not(feature = "ferrocene_certified"))]
234impl cmp::Ord for Alignment {
235 #[inline]
236 fn cmp(&self, other: &Self) -> cmp::Ordering {
237 self.as_nonzero().get().cmp(&other.as_nonzero().get())
238 }
239}
240
241#[unstable(feature = "ptr_alignment_type", issue = "102070")]
242#[cfg(not(feature = "ferrocene_certified"))]
243impl cmp::PartialOrd for Alignment {
244 #[inline]
245 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
246 Some(self.cmp(other))
247 }
248}
249
250#[unstable(feature = "ptr_alignment_type", issue = "102070")]
251#[cfg(not(feature = "ferrocene_certified"))]
252impl hash::Hash for Alignment {
253 #[inline]
254 fn hash<H: hash::Hasher>(&self, state: &mut H) {
255 self.as_nonzero().hash(state)
256 }
257}
258
259#[unstable(feature = "ptr_alignment_type", issue = "102070")]
261#[rustc_const_unstable(feature = "const_default", issue = "143894")]
262#[cfg(not(feature = "ferrocene_certified"))]
263impl const Default for Alignment {
264 fn default() -> Alignment {
265 Alignment::MIN
266 }
267}
268
269#[cfg(target_pointer_width = "16")]
270#[cfg_attr(not(feature = "ferrocene_certified"), derive(PartialEq, Eq))]
271#[derive(Copy, Clone)]
272#[repr(usize)]
273enum AlignmentEnum {
274 _Align1Shl0 = 1 << 0,
275 _Align1Shl1 = 1 << 1,
276 _Align1Shl2 = 1 << 2,
277 _Align1Shl3 = 1 << 3,
278 _Align1Shl4 = 1 << 4,
279 _Align1Shl5 = 1 << 5,
280 _Align1Shl6 = 1 << 6,
281 _Align1Shl7 = 1 << 7,
282 _Align1Shl8 = 1 << 8,
283 _Align1Shl9 = 1 << 9,
284 _Align1Shl10 = 1 << 10,
285 _Align1Shl11 = 1 << 11,
286 _Align1Shl12 = 1 << 12,
287 _Align1Shl13 = 1 << 13,
288 _Align1Shl14 = 1 << 14,
289 _Align1Shl15 = 1 << 15,
290}
291
292#[cfg(target_pointer_width = "32")]
293#[cfg_attr(not(feature = "ferrocene_certified"), derive(PartialEq, Eq))]
294#[derive(Copy, Clone)]
295#[repr(usize)]
296enum AlignmentEnum {
297 _Align1Shl0 = 1 << 0,
298 _Align1Shl1 = 1 << 1,
299 _Align1Shl2 = 1 << 2,
300 _Align1Shl3 = 1 << 3,
301 _Align1Shl4 = 1 << 4,
302 _Align1Shl5 = 1 << 5,
303 _Align1Shl6 = 1 << 6,
304 _Align1Shl7 = 1 << 7,
305 _Align1Shl8 = 1 << 8,
306 _Align1Shl9 = 1 << 9,
307 _Align1Shl10 = 1 << 10,
308 _Align1Shl11 = 1 << 11,
309 _Align1Shl12 = 1 << 12,
310 _Align1Shl13 = 1 << 13,
311 _Align1Shl14 = 1 << 14,
312 _Align1Shl15 = 1 << 15,
313 _Align1Shl16 = 1 << 16,
314 _Align1Shl17 = 1 << 17,
315 _Align1Shl18 = 1 << 18,
316 _Align1Shl19 = 1 << 19,
317 _Align1Shl20 = 1 << 20,
318 _Align1Shl21 = 1 << 21,
319 _Align1Shl22 = 1 << 22,
320 _Align1Shl23 = 1 << 23,
321 _Align1Shl24 = 1 << 24,
322 _Align1Shl25 = 1 << 25,
323 _Align1Shl26 = 1 << 26,
324 _Align1Shl27 = 1 << 27,
325 _Align1Shl28 = 1 << 28,
326 _Align1Shl29 = 1 << 29,
327 _Align1Shl30 = 1 << 30,
328 _Align1Shl31 = 1 << 31,
329}
330
331#[cfg(target_pointer_width = "64")]
332#[cfg_attr(not(feature = "ferrocene_certified"), derive(PartialEq, Eq))]
333#[derive(Copy, Clone)]
334#[repr(usize)]
335enum AlignmentEnum {
336 _Align1Shl0 = 1 << 0,
337 _Align1Shl1 = 1 << 1,
338 _Align1Shl2 = 1 << 2,
339 _Align1Shl3 = 1 << 3,
340 _Align1Shl4 = 1 << 4,
341 _Align1Shl5 = 1 << 5,
342 _Align1Shl6 = 1 << 6,
343 _Align1Shl7 = 1 << 7,
344 _Align1Shl8 = 1 << 8,
345 _Align1Shl9 = 1 << 9,
346 _Align1Shl10 = 1 << 10,
347 _Align1Shl11 = 1 << 11,
348 _Align1Shl12 = 1 << 12,
349 _Align1Shl13 = 1 << 13,
350 _Align1Shl14 = 1 << 14,
351 _Align1Shl15 = 1 << 15,
352 _Align1Shl16 = 1 << 16,
353 _Align1Shl17 = 1 << 17,
354 _Align1Shl18 = 1 << 18,
355 _Align1Shl19 = 1 << 19,
356 _Align1Shl20 = 1 << 20,
357 _Align1Shl21 = 1 << 21,
358 _Align1Shl22 = 1 << 22,
359 _Align1Shl23 = 1 << 23,
360 _Align1Shl24 = 1 << 24,
361 _Align1Shl25 = 1 << 25,
362 _Align1Shl26 = 1 << 26,
363 _Align1Shl27 = 1 << 27,
364 _Align1Shl28 = 1 << 28,
365 _Align1Shl29 = 1 << 29,
366 _Align1Shl30 = 1 << 30,
367 _Align1Shl31 = 1 << 31,
368 _Align1Shl32 = 1 << 32,
369 _Align1Shl33 = 1 << 33,
370 _Align1Shl34 = 1 << 34,
371 _Align1Shl35 = 1 << 35,
372 _Align1Shl36 = 1 << 36,
373 _Align1Shl37 = 1 << 37,
374 _Align1Shl38 = 1 << 38,
375 _Align1Shl39 = 1 << 39,
376 _Align1Shl40 = 1 << 40,
377 _Align1Shl41 = 1 << 41,
378 _Align1Shl42 = 1 << 42,
379 _Align1Shl43 = 1 << 43,
380 _Align1Shl44 = 1 << 44,
381 _Align1Shl45 = 1 << 45,
382 _Align1Shl46 = 1 << 46,
383 _Align1Shl47 = 1 << 47,
384 _Align1Shl48 = 1 << 48,
385 _Align1Shl49 = 1 << 49,
386 _Align1Shl50 = 1 << 50,
387 _Align1Shl51 = 1 << 51,
388 _Align1Shl52 = 1 << 52,
389 _Align1Shl53 = 1 << 53,
390 _Align1Shl54 = 1 << 54,
391 _Align1Shl55 = 1 << 55,
392 _Align1Shl56 = 1 << 56,
393 _Align1Shl57 = 1 << 57,
394 _Align1Shl58 = 1 << 58,
395 _Align1Shl59 = 1 << 59,
396 _Align1Shl60 = 1 << 60,
397 _Align1Shl61 = 1 << 61,
398 _Align1Shl62 = 1 << 62,
399 _Align1Shl63 = 1 << 63,
400}