Skip to main content

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}