Skip to main content

intid_core/
impls.rs

1//! Implementations of [`IntegerId`] for foreign types.
2
3macro_rules! impl_primint {
4    ($($target:ident),*) => {$(
5        impl crate::IntegerId for $target {
6            type Int = $target;
7            const MIN_ID: Option<Self> = Some(0);
8            const MAX_ID: Option<Self> = Some($target::MAX);
9            const MIN_ID_INT: Option<Self::Int> = Some(0);
10            const MAX_ID_INT: Option<Self::Int> = Some($target::MAX);
11            // SAFETY: Range is correct
12            const TRUSTED_RANGE: Option<crate::trusted::TrustedRangeToken<Self>> = unsafe { Some(crate::trusted::TrustedRangeToken::assume_valid()) };
13            #[inline]
14            fn from_int_checked(id: Self::Int) -> Option<Self> {
15                Some(id)
16            }
17            #[inline]
18            fn to_int(self) -> Self::Int {
19                self
20            }
21        }
22        impl crate::IntegerIdContiguous for $target {}
23        impl crate::IntegerIdCounter for $target {
24            const START: Self = 0;
25            const START_INT: Self = 0;
26        }
27    )*};
28}
29impl_primint!(u8, u16, u32, u64, u128, usize);
30// Can't use generic NonZero, because that requires Rust 1.79
31macro_rules! impl_nonzero_int {
32    ($($target:ident => $int:ident),*) => {$(
33        impl crate::IntegerId for core::num::$target {
34            type Int = $int;
35            const MIN_ID: Option<Self> = {
36                // while using NonZero::MIN might be nice, that requires rust 1.70
37                // SAFETY: One is not zero
38                unsafe {
39                    Some(core::num::$target::new_unchecked(1))
40                }
41            };
42            const MAX_ID: Option<Self> = {
43                // SAFETY: Maximum is not zero
44                unsafe {
45                    Some(core::num::$target::new_unchecked($int::MAX))
46                }
47            };
48            const MIN_ID_INT: Option<Self::Int> = Some(1);
49            const MAX_ID_INT: Option<Self::Int> = Some($int::MAX);
50            // SAFETY: Range is correct
51            const TRUSTED_RANGE: Option<crate::trusted::TrustedRangeToken<Self>> = unsafe { Some(crate::trusted::TrustedRangeToken::assume_valid()) };
52
53            #[inline]
54            fn from_int_checked(id: Self::Int) -> Option<Self> {
55                core::num::$target::new(id)
56            }
57
58            #[inline]
59            unsafe fn from_int_unchecked(id: Self::Int) -> Self {
60                // SAFETY: Guaranteed by caller
61                unsafe {
62                    core::num::$target::new_unchecked(id)
63                }
64            }
65
66            #[inline]
67            fn to_int(self) -> Self::Int {
68                self.get()
69            }
70        }
71        impl crate::IntegerIdContiguous for core::num::$target {}
72        impl crate::IntegerIdCounter for core::num::$target {
73            const START: Self = match <Self as crate::IntegerId>::MIN_ID {
74                Some(valid) => valid,
75                None => panic!("type should be inhabited")
76            };
77            const START_INT: $int = Self::START.get();
78        }
79    )*}
80}
81impl_nonzero_int!(
82    NonZeroU8 => u8,
83    NonZeroU16 => u16,
84    NonZeroU32 => u32,
85    NonZeroU64 => u64,
86    NonZeroU128 => u128,
87    NonZeroUsize => usize
88);
89
90#[cfg(feature = "nonmax")]
91macro_rules! do_nonmax_impl {
92    ($($target:ident => $int:ident),*) => {$(
93        impl crate::IntegerId for nonmax::$target {
94            type Int = $int;
95            const MIN_ID: Option<Self> = Some(nonmax::$target::ZERO);
96            const MAX_ID: Option<Self> = Some(nonmax::$target::MAX);
97            const MIN_ID_INT: Option<Self::Int> = Some(0);
98            const MAX_ID_INT: Option<Self::Int> = Some(nonmax::$target::MAX.get());
99            // SAFETY: Range is correct
100            const TRUSTED_RANGE: Option<crate::trusted::TrustedRangeToken<Self>> = unsafe { Some(crate::trusted::TrustedRangeToken::assume_valid()) };
101
102            #[inline]
103            fn from_int_checked(id: Self::Int) -> Option<Self> {
104                nonmax::$target::new(id)
105            }
106            #[inline]
107            unsafe fn from_int_unchecked(id: Self::Int) -> Self {
108                // SAFETY: Guaranteed by caller
109                unsafe { nonmax::$target::new_unchecked(id) }
110            }
111            #[inline]
112            fn to_int(self) -> Self::Int {
113                self.get()
114            }
115        }
116        impl crate::IntegerIdContiguous for nonmax::$target {
117        }
118        impl crate::IntegerIdCounter for nonmax::$target {
119            const START: Self = nonmax::$target::ZERO;
120            const START_INT: Self::Int = 0;
121        }
122    )*};
123}
124#[cfg(feature = "nonmax")]
125do_nonmax_impl!(NonMaxU8 => u8, NonMaxU16 => u16, NonMaxU32 => u32, NonMaxU64 => u64, NonMaxU128 => u128, NonMaxUsize => usize);
126
127macro_rules! impl_uninhabited {
128    ($target:ty) => {
129        impl crate::IntegerId for $target {
130            type Int = u8;
131            const MIN_ID: Option<Self> = None;
132            const MAX_ID: Option<Self> = None;
133            const MIN_ID_INT: Option<Self::Int> = None;
134            const MAX_ID_INT: Option<Self::Int> = None;
135            const TRUSTED_RANGE: Option<crate::trusted::TrustedRangeToken<Self>> = {
136                // SAFETY: Range is correct (vacuously)
137                unsafe { Some(crate::trusted::TrustedRangeToken::assume_valid()) }
138            };
139
140            #[track_caller]
141            #[inline]
142            fn from_int(id: Self::Int) -> Self {
143                panic!(
144                    "Cannot initialize uninhabited type {this} with {id}",
145                    this = stringify!($target),
146                )
147            }
148
149            #[inline]
150            fn from_int_checked(_id: Self::Int) -> Option<Self> {
151                None
152            }
153
154            #[inline]
155            unsafe fn from_int_unchecked(_id: Self::Int) -> Self {
156                // SAFETY: Caller guarantees this is called only if `id` is a valid index,
157                // and there are no valid indices
158                unsafe {
159                    core::hint::unreachable_unchecked();
160                }
161            }
162
163            #[inline]
164            fn to_int(self) -> Self::Int {
165                match self {}
166            }
167        }
168        impl crate::IntegerIdContiguous for $target {}
169    };
170}
171impl_uninhabited!(core::convert::Infallible);
172#[cfg(feature = "nightly")]
173impl_uninhabited!(!);