xref: /wasmtime-44.0.1/crates/core/src/non_max.rs (revision 59d23a35)
1 //! Integer newtypes that are guaranteed not to be their maximum value.
2 
3 macro_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 
88 define_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 }
95