1#![forbid(missing_docs)]
57#![cfg_attr(not(feature = "std"), no_std)]
58
59#[derive(Debug, Clone, Copy, PartialEq, Eq)]
61pub struct TryFromIntError(());
62
63#[cfg(feature = "std")]
64impl std::error::Error for TryFromIntError {}
65
66impl core::fmt::Display for TryFromIntError {
67    fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
68        "out of range integral type conversion attempted".fmt(fmt)
69    }
70}
71
72impl From<core::num::TryFromIntError> for TryFromIntError {
73    fn from(_: core::num::TryFromIntError) -> Self {
74        Self(())
75    }
76}
77
78impl From<core::convert::Infallible> for TryFromIntError {
79    fn from(never: core::convert::Infallible) -> Self {
80        match never {}
81    }
82}
83
84#[derive(Clone, Debug, PartialEq, Eq)]
86pub struct ParseIntError(());
87
88#[cfg(feature = "std")]
89impl std::error::Error for ParseIntError {}
90
91impl core::fmt::Display for ParseIntError {
92    fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
93        "unable to parse integer".fmt(fmt)
94    }
95}
96
97impl From<core::num::ParseIntError> for ParseIntError {
98    fn from(_: core::num::ParseIntError) -> Self {
99        Self(())
100    }
101}
102
103macro_rules! impl_nonmax_fmt {
109    ( ( $( $Trait: ident ),+ ) for $nonmax: ident ) => {
110        $(
111            impl core::fmt::$Trait for $nonmax {
112                #[inline]
113                fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
114                    core::fmt::$Trait::fmt(&self.get(), f)
115                }
116            }
117        )+
118    };
119}
120
121macro_rules! nonmax {
122    ( common, $nonmax: ident, $non_zero: ident, $primitive: ident ) => {
123        #[derive(Clone, Copy, PartialEq, Eq, Hash)]
125        #[repr(transparent)]
126        pub struct $nonmax(core::num::$non_zero);
127
128        impl $nonmax {
129            #[inline]
132            pub const fn new(value: $primitive) -> Option<Self> {
133                match core::num::$non_zero::new(value ^ $primitive::MAX) {
134                    None => None,
135                    Some(value) => Some(Self(value)),
136                }
137            }
138
139            #[inline]
146            pub const unsafe fn new_unchecked(value: $primitive) -> Self {
147                let inner = core::num::$non_zero::new_unchecked(value ^ $primitive::MAX);
148                Self(inner)
149            }
150
151            #[inline]
153            pub const fn get(&self) -> $primitive {
154                self.0.get() ^ $primitive::MAX
155            }
156
157            pub const ZERO: $nonmax = unsafe { Self::new_unchecked(0) };
159
160            pub const ONE: $nonmax = unsafe { Self::new_unchecked(1) };
162
163            pub const MAX: $nonmax = unsafe { Self::new_unchecked($primitive::MAX - 1) };
165        }
166
167        impl Default for $nonmax {
168            fn default() -> Self {
169                unsafe { Self::new_unchecked(0) }
170            }
171        }
172
173        impl From<$nonmax> for $primitive {
174            fn from(value: $nonmax) -> Self {
175                value.get()
176            }
177        }
178
179        impl core::convert::TryFrom<$primitive> for $nonmax {
180            type Error = TryFromIntError;
181            fn try_from(value: $primitive) -> Result<Self, Self::Error> {
182                Self::new(value).ok_or(TryFromIntError(()))
183            }
184        }
185
186        impl core::str::FromStr for $nonmax {
187            type Err = ParseIntError;
188            fn from_str(value: &str) -> Result<Self, Self::Err> {
189                Self::new($primitive::from_str(value)?).ok_or(ParseIntError(()))
190            }
191        }
192
193        impl core::cmp::Ord for $nonmax {
194            fn cmp(&self, other: &Self) -> core::cmp::Ordering {
195                self.get().cmp(&other.get())
196            }
197        }
198        impl core::cmp::PartialOrd for $nonmax {
199            fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
200                Some(self.cmp(other))
201            }
202        }
203
204        impl core::ops::BitAnd<$nonmax> for $nonmax {
209            type Output = $nonmax;
210            fn bitand(self, rhs: $nonmax) -> Self::Output {
211                unsafe { $nonmax::new_unchecked(self.get() & rhs.get()) }
214            }
215        }
216
217        impl core::ops::BitAndAssign<$nonmax> for $nonmax {
218            fn bitand_assign(&mut self, rhs: $nonmax) {
219                *self = *self & rhs;
220            }
221        }
222
223        impl_nonmax_fmt! {
225            (Debug, Display, Binary, Octal, LowerHex, UpperHex) for $nonmax
226        }
227
228        #[cfg(feature = "serde")]
229        impl serde::Serialize for $nonmax {
230            fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
231            where
232                S: serde::Serializer,
233            {
234                self.get().serialize(serializer)
235            }
236        }
237
238        #[cfg(feature = "serde")]
239        impl<'de> serde::Deserialize<'de> for $nonmax {
240            fn deserialize<D>(deserializer: D) -> Result<$nonmax, D::Error>
241            where
242                D: serde::Deserializer<'de>,
243            {
244                let value = $primitive::deserialize(deserializer)?;
245                use core::convert::TryFrom;
246                Self::try_from(value).map_err(serde::de::Error::custom)
247            }
248        }
249
250        #[cfg(test)]
251        mod $primitive {
252            use super::*;
253
254            use core::mem::size_of;
255
256            #[test]
257            fn construct() {
258                let zero = $nonmax::new(0).unwrap();
259                assert_eq!(zero.get(), 0);
260
261                let some = $nonmax::new(19).unwrap();
262                assert_eq!(some.get(), 19);
263
264                let max = $nonmax::new($primitive::MAX);
265                assert_eq!(max, None);
266            }
267
268            #[test]
269            fn sizes_correct() {
270                assert_eq!(size_of::<$primitive>(), size_of::<$nonmax>());
271                assert_eq!(size_of::<$nonmax>(), size_of::<Option<$nonmax>>());
272            }
273
274            #[test]
275            fn convert() {
276                use core::convert::TryFrom;
277                let zero = $nonmax::try_from(0 as $primitive).unwrap();
278                let zero = $primitive::from(zero);
279                assert_eq!(zero, 0);
280
281                $nonmax::try_from($primitive::MAX).unwrap_err();
282            }
283
284            #[test]
285            fn cmp() {
286                let zero = $nonmax::new(0).unwrap();
287                let one = $nonmax::new(1).unwrap();
288                let two = $nonmax::new(2).unwrap();
289                assert!(zero < one);
290                assert!(one < two);
291                assert!(two > one);
292                assert!(one > zero);
293            }
294
295            #[test]
296            fn constants() {
297                let zero = $nonmax::ZERO;
298                let one = $nonmax::ONE;
299                let max = $nonmax::MAX;
300                assert_eq!(zero.get(), 0);
301                assert_eq!(one.get(), 1);
302                assert_eq!(max.get(), $primitive::MAX - 1);
303            }
304
305            #[test]
306            #[cfg(feature = "std")] fn parse() {
308                for value in [0, 19, $primitive::MAX - 1].iter().copied() {
309                    let string = value.to_string();
310                    let nonmax = string.parse::<$nonmax>().unwrap();
311                    assert_eq!(nonmax.get(), value);
312                }
313                $primitive::MAX.to_string().parse::<$nonmax>().unwrap_err();
314            }
315
316            #[test]
317            #[cfg(feature = "std")] fn fmt() {
319                let zero = $nonmax::new(0).unwrap();
320                let some = $nonmax::new(19).unwrap();
321                let max1 = $nonmax::new($primitive::MAX - 1).unwrap();
322                for value in [zero, some, max1].iter().copied() {
323                    assert_eq!(format!("{}", value.get()), format!("{}", value)); assert_eq!(format!("{:?}", value.get()), format!("{:?}", value)); assert_eq!(format!("{:b}", value.get()), format!("{:b}", value)); assert_eq!(format!("{:o}", value.get()), format!("{:o}", value)); assert_eq!(format!("{:x}", value.get()), format!("{:x}", value)); assert_eq!(format!("{:X}", value.get()), format!("{:X}", value)); }
330            }
331
332            #[test]
333            #[cfg(feature = "serde")]
334            fn serde() {
335                for &value in [0, 19, $primitive::MAX - 1].iter() {
336                    let nonmax_value = $nonmax::new(value).unwrap();
337                    let encoded: Vec<u8> = bincode::serialize(&nonmax_value).unwrap();
338                    let decoded: $nonmax = bincode::deserialize(&encoded[..]).unwrap();
339                    assert_eq!(nonmax_value, decoded);
340                }
341            }
342        }
343    };
344
345    ( signed, $nonmax: ident, $non_zero: ident, $primitive: ident ) => {
346        nonmax!(common, $nonmax, $non_zero, $primitive);
347        };
349
350    ( unsigned, $nonmax: ident, $non_zero: ident, $primitive: ident ) => {
351        nonmax!(common, $nonmax, $non_zero, $primitive);
352
353        impl core::ops::BitAnd<$nonmax> for $primitive {
354            type Output = $nonmax;
355            fn bitand(self, rhs: $nonmax) -> Self::Output {
356                unsafe { $nonmax::new_unchecked(self & rhs.get()) }
359            }
360        }
361
362        impl core::ops::BitAnd<$primitive> for $nonmax {
363            type Output = $nonmax;
364            fn bitand(self, rhs: $primitive) -> Self::Output {
365                unsafe { $nonmax::new_unchecked(self.get() & rhs) }
368            }
369        }
370
371        impl core::ops::BitAndAssign<$primitive> for $nonmax {
372            fn bitand_assign(&mut self, rhs: $primitive) {
373                *self = *self & rhs;
374            }
375        }
376
377        impl core::ops::BitAndAssign<$nonmax> for $primitive {
379            fn bitand_assign(&mut self, rhs: $nonmax) {
380                *self = *self & rhs.get();
381            }
382        }
383    };
384}
385
386nonmax!(signed, NonMaxI8, NonZeroI8, i8);
387nonmax!(signed, NonMaxI16, NonZeroI16, i16);
388nonmax!(signed, NonMaxI32, NonZeroI32, i32);
389nonmax!(signed, NonMaxI64, NonZeroI64, i64);
390nonmax!(signed, NonMaxI128, NonZeroI128, i128);
391nonmax!(signed, NonMaxIsize, NonZeroIsize, isize);
392
393nonmax!(unsigned, NonMaxU8, NonZeroU8, u8);
394nonmax!(unsigned, NonMaxU16, NonZeroU16, u16);
395nonmax!(unsigned, NonMaxU32, NonZeroU32, u32);
396nonmax!(unsigned, NonMaxU64, NonZeroU64, u64);
397nonmax!(unsigned, NonMaxU128, NonZeroU128, u128);
398nonmax!(unsigned, NonMaxUsize, NonZeroUsize, usize);
399
400macro_rules! impl_nonmax_from {
402    ( $small: ty, $large: ty ) => {
403        impl From<$small> for $large {
404            #[inline]
405            fn from(small: $small) -> Self {
406                unsafe { Self::new_unchecked(small.get().into()) }
408            }
409        }
410    };
411}
412
413impl_nonmax_from!(NonMaxU8, NonMaxU16);
415impl_nonmax_from!(NonMaxU8, NonMaxU32);
416impl_nonmax_from!(NonMaxU8, NonMaxU64);
417impl_nonmax_from!(NonMaxU8, NonMaxU128);
418impl_nonmax_from!(NonMaxU8, NonMaxUsize);
419impl_nonmax_from!(NonMaxU16, NonMaxU32);
420impl_nonmax_from!(NonMaxU16, NonMaxU64);
421impl_nonmax_from!(NonMaxU16, NonMaxU128);
422impl_nonmax_from!(NonMaxU16, NonMaxUsize);
423impl_nonmax_from!(NonMaxU32, NonMaxU64);
424impl_nonmax_from!(NonMaxU32, NonMaxU128);
425impl_nonmax_from!(NonMaxU64, NonMaxU128);
426
427impl_nonmax_from!(NonMaxI8, NonMaxI16);
429impl_nonmax_from!(NonMaxI8, NonMaxI32);
430impl_nonmax_from!(NonMaxI8, NonMaxI64);
431impl_nonmax_from!(NonMaxI8, NonMaxI128);
432impl_nonmax_from!(NonMaxI8, NonMaxIsize);
433impl_nonmax_from!(NonMaxI16, NonMaxI32);
434impl_nonmax_from!(NonMaxI16, NonMaxI64);
435impl_nonmax_from!(NonMaxI16, NonMaxI128);
436impl_nonmax_from!(NonMaxI16, NonMaxIsize);
437impl_nonmax_from!(NonMaxI32, NonMaxI64);
438impl_nonmax_from!(NonMaxI32, NonMaxI128);
439impl_nonmax_from!(NonMaxI64, NonMaxI128);
440
441impl_nonmax_from!(NonMaxU8, NonMaxI16);
443impl_nonmax_from!(NonMaxU8, NonMaxI32);
444impl_nonmax_from!(NonMaxU8, NonMaxI64);
445impl_nonmax_from!(NonMaxU8, NonMaxI128);
446impl_nonmax_from!(NonMaxU8, NonMaxIsize);
447impl_nonmax_from!(NonMaxU16, NonMaxI32);
448impl_nonmax_from!(NonMaxU16, NonMaxI64);
449impl_nonmax_from!(NonMaxU16, NonMaxI128);
450impl_nonmax_from!(NonMaxU32, NonMaxI64);
451impl_nonmax_from!(NonMaxU32, NonMaxI128);
452impl_nonmax_from!(NonMaxU64, NonMaxI128);
453
454macro_rules! impl_smaller_from {
456    ( $small: ty, $large: ty ) => {
457        impl From<$small> for $large {
458            #[inline]
459            fn from(small: $small) -> Self {
460                unsafe { Self::new_unchecked(small.into()) }
462            }
463        }
464    };
465}
466
467impl_smaller_from!(u8, NonMaxU16);
469impl_smaller_from!(u8, NonMaxU32);
470impl_smaller_from!(u8, NonMaxU64);
471impl_smaller_from!(u8, NonMaxU128);
472impl_smaller_from!(u8, NonMaxUsize);
473impl_smaller_from!(u16, NonMaxU32);
474impl_smaller_from!(u16, NonMaxU64);
475impl_smaller_from!(u16, NonMaxU128);
476impl_smaller_from!(u16, NonMaxUsize);
477impl_smaller_from!(u32, NonMaxU64);
478impl_smaller_from!(u32, NonMaxU128);
479impl_smaller_from!(u64, NonMaxU128);
480
481impl_smaller_from!(i8, NonMaxI16);
483impl_smaller_from!(i8, NonMaxI32);
484impl_smaller_from!(i8, NonMaxI64);
485impl_smaller_from!(i8, NonMaxI128);
486impl_smaller_from!(i8, NonMaxIsize);
487impl_smaller_from!(i16, NonMaxI32);
488impl_smaller_from!(i16, NonMaxI64);
489impl_smaller_from!(i16, NonMaxI128);
490impl_smaller_from!(i16, NonMaxIsize);
491impl_smaller_from!(i32, NonMaxI64);
492impl_smaller_from!(i32, NonMaxI128);
493impl_smaller_from!(i64, NonMaxI128);
494
495impl_smaller_from!(u8, NonMaxI16);
497impl_smaller_from!(u8, NonMaxI32);
498impl_smaller_from!(u8, NonMaxI64);
499impl_smaller_from!(u8, NonMaxI128);
500impl_smaller_from!(u8, NonMaxIsize);
501impl_smaller_from!(u16, NonMaxI32);
502impl_smaller_from!(u16, NonMaxI64);
503impl_smaller_from!(u16, NonMaxI128);
504impl_smaller_from!(u32, NonMaxI64);
505impl_smaller_from!(u32, NonMaxI128);
506impl_smaller_from!(u64, NonMaxI128);
507
508#[cfg(test)]
509mod ops {
510    use super::*;
511
512    #[test]
513    fn bitand_unsigned() {
514        for left in 0..=u8::MAX {
515            let nmleft = NonMaxU8::new(left);
516            for right in 0..=u8::MAX {
517                let nmright = NonMaxU8::new(right);
518                let vanilla = left & right;
519
520                if let (Some(nmleft), Some(nmright)) = (nmleft, nmright) {
521                    assert_eq!(vanilla, (nmleft & nmright).get());
522                }
523                if let Some(nmleft) = nmleft {
524                    assert_eq!(vanilla, (nmleft & right).get());
525                }
526                if let Some(nmright) = nmright {
527                    assert_eq!(vanilla, (left & nmright).get());
528                }
529            }
530        }
531    }
532
533    #[test]
534    fn bitand_signed() {
535        for left in i8::MIN..=i8::MAX {
536            let nmleft = NonMaxI8::new(left);
537            for right in i8::MIN..=i8::MAX {
538                let nmright = NonMaxI8::new(right);
539                let vanilla = left & right;
540                if let (Some(nmleft), Some(nmright)) = (nmleft, nmright) {
541                    assert_eq!(vanilla, (nmleft & nmright).get());
542                }
543            }
544        }
545    }
546}