wasmtime_internal_core/non_max.rs
1//! Integer newtypes that are guaranteed not to be their maximum value.
2
3macro_rules! define_non_max {
4 ( $(
5 $( #[ $attr:meta ] )*
6 pub struct $non_max:ident($non_zero:ty) : $prim:ty;
7 )* ) => {
8 $(
9 /// A
10 #[doc = concat!("`", stringify!($prim), "`")]
11 /// value that is known not to be
12 #[doc = concat!("`", stringify!($prim), "::MAX`.")]
13 ///
14 /// This enables some memory layout optimizations. For example,
15 #[doc = concat!("`Option<", stringify!($prim), ">`")]
16 /// is the same size as
17 #[doc = concat!("`", stringify!($prim), "`:")]
18 ///
19 /// ```
20 /// # use wasmtime_internal_core::non_max::NonMaxU32;
21 /// assert_eq!(
22 /// core::mem::size_of::<u32>(),
23 /// core::mem::size_of::<Option<NonMaxU32>>(),
24 /// );
25 /// ```
26 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
27 pub struct $non_max($non_zero);
28
29 impl Default for $non_max {
30 fn default() -> Self {
31 Self::new(0).unwrap()
32 }
33 }
34
35 impl core::fmt::Debug for $non_max {
36 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
37 f.debug_tuple(stringify!($non_max))
38 .field(&self.get())
39 .finish()
40 }
41 }
42
43 impl $non_max {
44 /// Construct a new
45 #[doc = concat!("`", stringify!($prim), "`")]
46 /// value.
47 ///
48 /// Returns `None` when given
49 #[doc = concat!("`", stringify!($prim), "::MAX`.")]
50 #[inline]
51 pub fn new(x: $prim) -> Option<Self> {
52 if x == <$prim>::MAX {
53 None
54 } else {
55 // Safety: `x != $prim::MAX`.
56 Some(unsafe { Self::new_unchecked(x) })
57 }
58 }
59
60 /// Unsafely construct a new
61 #[doc = concat!("`", stringify!($prim), "`")]
62 /// value.
63 ///
64 /// # Safety
65 ///
66 /// The given value must not be
67 #[doc = concat!("`", stringify!($prim), "::MAX`.")]
68 #[inline]
69 pub unsafe fn new_unchecked(x: $prim) -> Self {
70 debug_assert_ne!(x, <$prim>::MAX);
71 // Safety: We know that `x+1` is non-zero because it will not
72 // overflow because `x` is not `$prim::MAX`.
73 Self(unsafe { <$non_zero>::new_unchecked(x + 1) })
74 }
75
76 /// Get the underlying
77 #[doc = concat!("`", stringify!($prim), "`")]
78 /// value.
79 #[inline]
80 pub fn get(&self) -> $prim {
81 self.0.get() - 1
82 }
83 }
84 )*
85 };
86}
87
88define_non_max! {
89 pub struct NonMaxU8(core::num::NonZeroU8) : u8;
90 pub struct NonMaxU16(core::num::NonZeroU16) : u16;
91 pub struct NonMaxU32(core::num::NonZeroU32) : u32;
92 pub struct NonMaxU64(core::num::NonZeroU64) : u64;
93 pub struct NonMaxUsize(core::num::NonZeroUsize) : usize;
94}