ordinal_map/ordinal/impls/
non_zero.rs1use std::num::NonZeroI16;
2use std::num::NonZeroI32;
3use std::num::NonZeroI64;
4use std::num::NonZeroI8;
5use std::num::NonZeroIsize;
6use std::num::NonZeroU16;
7use std::num::NonZeroU32;
8use std::num::NonZeroU64;
9use std::num::NonZeroU8;
10use std::num::NonZeroUsize;
11
12use crate::Ordinal;
13
14impl Ordinal for NonZeroU8 {
15 const ORDINAL_SIZE: usize = u8::MAX as usize;
16
17 #[inline]
18 fn ordinal(&self) -> usize {
19 self.get() as usize - 1
20 }
21
22 #[inline]
23 fn from_ordinal(ordinal: usize) -> Option<Self> {
24 NonZeroU8::try_from(u8::try_from(ordinal.checked_add(1)?).ok()?).ok()
25 }
26}
27
28impl Ordinal for NonZeroI8 {
29 const ORDINAL_SIZE: usize = NonZeroU8::ORDINAL_SIZE;
30
31 #[inline]
32 fn ordinal(&self) -> usize {
33 if self.get() > 0 {
34 127 + self.get() as usize
35 } else {
36 self.get().abs_diff(i8::MIN) as usize
37 }
38 }
39
40 #[inline]
41 fn from_ordinal(ordinal: usize) -> Option<Self> {
42 match ordinal.checked_sub(i8::MAX as usize + 1) {
43 None => NonZeroI8::new(
44 i8::MIN
45 .checked_add_unsigned(u8::try_from(ordinal).unwrap())
46 .unwrap(),
47 ),
48 Some(rem) => NonZeroI8::new(i8::try_from(rem + 1).ok()?),
49 }
50 }
51}
52
53impl Ordinal for NonZeroU16 {
54 const ORDINAL_SIZE: usize = u16::MAX as usize;
55
56 #[inline]
57 fn ordinal(&self) -> usize {
58 self.get() as usize - 1
59 }
60
61 #[inline]
62 fn from_ordinal(ordinal: usize) -> Option<Self> {
63 NonZeroU16::try_from(u16::try_from(ordinal.checked_add(1)?).ok()?).ok()
64 }
65}
66
67impl Ordinal for NonZeroI16 {
68 const ORDINAL_SIZE: usize = NonZeroU16::ORDINAL_SIZE;
69
70 #[inline]
71 fn ordinal(&self) -> usize {
72 if self.get() > 0 {
73 32767 + self.get() as usize
74 } else {
75 self.get().abs_diff(i16::MIN) as usize
76 }
77 }
78
79 #[inline]
80 fn from_ordinal(ordinal: usize) -> Option<Self> {
81 match ordinal.checked_sub(i16::MAX as usize + 1) {
82 None => NonZeroI16::new(
83 i16::MIN
84 .checked_add_unsigned(u16::try_from(ordinal).unwrap())
85 .unwrap(),
86 ),
87 Some(rem) => NonZeroI16::new(i16::try_from(rem + 1).ok()?),
88 }
89 }
90}
91
92impl Ordinal for NonZeroU32 {
93 const ORDINAL_SIZE: usize = u32::MAX as usize;
94
95 #[inline]
96 fn ordinal(&self) -> usize {
97 self.get() as usize - 1
98 }
99
100 #[inline]
101 fn from_ordinal(ordinal: usize) -> Option<Self> {
102 NonZeroU32::try_from(u32::try_from(ordinal.checked_add(1)?).ok()?).ok()
103 }
104}
105
106impl Ordinal for NonZeroI32 {
107 const ORDINAL_SIZE: usize = NonZeroU32::ORDINAL_SIZE;
108
109 #[inline]
110 fn ordinal(&self) -> usize {
111 if self.get() > 0 {
112 2147483647 + self.get() as usize
113 } else {
114 self.get().abs_diff(i32::MIN) as usize
115 }
116 }
117
118 #[inline]
119 fn from_ordinal(ordinal: usize) -> Option<Self> {
120 match ordinal.checked_sub(i32::MAX as usize + 1) {
121 None => NonZeroI32::new(
122 i32::MIN
123 .checked_add_unsigned(u32::try_from(ordinal).unwrap())
124 .unwrap(),
125 ),
126 Some(rem) => NonZeroI32::new(i32::try_from(rem + 1).ok()?),
127 }
128 }
129}
130
131impl Ordinal for NonZeroUsize {
132 const ORDINAL_SIZE: usize = usize::MAX;
133
134 #[inline]
135 fn ordinal(&self) -> usize {
136 self.get() - 1
137 }
138
139 #[inline]
140 fn from_ordinal(ordinal: usize) -> Option<Self> {
141 NonZeroUsize::new(ordinal.checked_add(1)?)
142 }
143}
144
145impl Ordinal for NonZeroIsize {
146 const ORDINAL_SIZE: usize = NonZeroUsize::ORDINAL_SIZE;
147
148 #[inline]
149 fn ordinal(&self) -> usize {
150 if self.get() > 0 {
151 usize::MAX / 2 + self.get() as usize
152 } else {
153 self.get().abs_diff(isize::MIN)
154 }
155 }
156
157 #[inline]
158 fn from_ordinal(ordinal: usize) -> Option<Self> {
159 match ordinal.checked_sub(isize::MAX as usize + 1) {
160 None => NonZeroIsize::new(isize::MIN.checked_add_unsigned(ordinal).unwrap()),
161 Some(rem) => NonZeroIsize::new(isize::try_from(rem + 1).ok()?),
162 }
163 }
164}
165
166impl Ordinal for NonZeroU64 {
168 const ORDINAL_SIZE: usize = if u64::MAX == usize::MAX as u64 {
169 usize::MAX
170 } else {
171 panic!("NonZeroU64::ORDINAL_SIZE is too large for 32-bit platforms")
172 };
173
174 fn ordinal(&self) -> usize {
175 const { Self::ORDINAL_SIZE };
176 NonZeroUsize::new(self.get() as usize).unwrap().ordinal()
177 }
178
179 fn from_ordinal(ordinal: usize) -> Option<Self> {
180 const { Self::ORDINAL_SIZE };
181 Some(NonZeroU64::new(NonZeroUsize::from_ordinal(ordinal)?.get() as u64).unwrap())
182 }
183}
184
185impl Ordinal for NonZeroI64 {
186 const ORDINAL_SIZE: usize = NonZeroU64::ORDINAL_SIZE;
187
188 fn ordinal(&self) -> usize {
189 const { Self::ORDINAL_SIZE };
190 NonZeroIsize::new(self.get() as isize).unwrap().ordinal()
191 }
192
193 fn from_ordinal(ordinal: usize) -> Option<Self> {
194 const { Self::ORDINAL_SIZE };
195 Some(NonZeroI64::new(NonZeroIsize::from_ordinal(ordinal)?.get() as i64).unwrap())
196 }
197}
198
199#[cfg(test)]
200mod tests {
201 use std::num::NonZeroI16;
202 use std::num::NonZeroI32;
203 use std::num::NonZeroI64;
204 use std::num::NonZeroI8;
205 use std::num::NonZeroIsize;
206 use std::num::NonZeroU16;
207 use std::num::NonZeroU64;
208 use std::num::NonZeroU8;
209 use std::num::NonZeroUsize;
210
211 use crate::tests::util::test_ordinal;
212 use crate::tests::util::test_ordinal_some;
213 use crate::tests::util::test_ordinal_value;
214
215 #[test]
216 fn test_non_zero_u8() {
217 test_ordinal((1..=u8::MAX).map(|i| NonZeroU8::new(i).unwrap()));
218 }
219
220 #[test]
221 fn test_non_zero_i8() {
222 test_ordinal((i8::MIN..=i8::MAX).filter_map(NonZeroI8::new));
223 }
224
225 #[test]
226 fn test_non_zero_u16() {
227 test_ordinal((1..=u16::MAX).map(|i| NonZeroU16::new(i).unwrap()));
228 }
229
230 #[test]
231 fn test_non_zero_i16() {
232 test_ordinal((i16::MIN..=i16::MAX).filter_map(NonZeroI16::new));
233 }
234
235 #[test]
236 fn test_non_zero_u32() {
237 test_ordinal_some::<u32>();
238 }
239
240 #[test]
241 fn test_non_zero_i32() {
242 test_ordinal_some::<i32>();
243 test_ordinal_value(NonZeroI32::new(-1));
244 test_ordinal_value(NonZeroI32::new(1));
245 }
246
247 #[test]
248 fn test_non_zero_u64() {
249 if cfg!(target_pointer_width = "64") {
250 test_ordinal_some::<NonZeroU64>();
251 }
252 }
253
254 #[test]
255 fn test_non_zero_i64() {
256 if cfg!(target_pointer_width = "64") {
257 test_ordinal_some::<NonZeroI64>();
258 test_ordinal_value(NonZeroI64::new(-1));
259 test_ordinal_value(NonZeroI64::new(1));
260 }
261 }
262
263 #[test]
264 fn test_non_zero_usize() {
265 test_ordinal_some::<NonZeroUsize>();
266 }
267
268 #[test]
269 fn test_non_zero_isize() {
270 test_ordinal_some::<NonZeroIsize>();
271 test_ordinal_value(NonZeroIsize::new(-1));
272 test_ordinal_value(NonZeroIsize::new(1));
273 }
274}