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