sign_bound/
lib.rs

1//! # sign-bound
2//!
3//! Signed integer types for Rust that are bounded to be either positive or negative. The API is
4//! analogous to the built-in [`NonZero`] types. The types are all memory-layout optimized, so for
5//! example `Option<PositiveI32>` and `Option<NegativeI32>` are both the same size as `i32`. Using
6//! additional variants in an enum can also have some space benefits.
7//!
8//! ```rust
9//! # use sign_bound::PositiveI16;
10//! enum MyEnum {
11//!     A(PositiveI16),
12//!     B,
13//!     C,
14//!     D,
15//! }
16//! assert_eq!(size_of::<MyEnum>(), size_of::<PositiveI16>());
17//! ```
18//!
19//! Note that due to the implementation details of this crate, the space
20//! optimization for any type will not occur if there are more than 128 additional
21//! enum variants.
22//!
23//! `Option<PositiveIsize>` is particularly useful as a space-efficient optional
24//! `Vec` index, since Rust's `Vec` structure is
25//! [limited](https://doc.rust-lang.org/std/vec/struct.Vec.html#method.push) to
26//! `isize::MAX` entries.
27//!
28//! [`NonZero`]: (https://doc.rust-lang.org/std/num/struct.NonZero.html)
29
30#![deny(missing_docs)]
31#![no_std]
32
33macro_rules! impl_positive {
34    ($(#[$attr:meta])* $ty:ident, $sty:ident, $d:tt $mac:ident, $base:ty, $uns:ty) => {
35
36        #[doc = concat!("Creates a [`", stringify!($ty), "`] checked at compile time.")]
37        ///
38        #[doc = concat!("This macro takes a single argument that must be a positive [`", stringify!($base), "`].")]
39        /// Negative values will cause a compile error.
40        ///
41        /// ```rust
42        #[doc = concat!("use sign_bound::{", stringify!($ty), ", ", stringify!($mac), "};")]
43        ///
44        #[doc = concat!("let val: ", stringify!($ty), " = ", stringify!($mac), "!(123);")]
45        /// ```
46        #[macro_export]
47        macro_rules! $mac {
48            ($e:expr $d(,)?) => {
49                const {
50                    match $crate::$ty::new($e) {
51                        ::core::option::Option::Some(e) => e,
52                        _ => panic!(concat!(stringify!($base), " out of range for ", stringify!($ty))),
53                    }
54                }
55            };
56        }
57
58        /// A signed value that is known to be positive.
59        ///
60        /// This enables some memory layout optimization.
61        #[doc = concat!("For example, `Option<", stringify!($ty), ">` is the same size as [`", stringify!($base), "`].")]
62        #[derive(Copy, Clone)]
63        #[repr(C)]
64        $(#[$attr])*
65        pub struct $ty {
66            #[cfg(target_endian = "big")]
67            _hi: PositiveHighByte,
68            _buf: [u8; size_of::<$base>() - 1],
69            #[cfg(target_endian = "little")]
70            _hi: PositiveHighByte,
71        }
72
73        impl $ty {
74            /// The size of this positive integer type in bits.
75            ///
76            #[doc = concat!("This value is equal to [`", stringify!($base), "::BITS`].")]
77            pub const BITS: u32 = <$base>::BITS;
78            /// The smallest value that can be represented by this positive integer type, 0.
79            pub const MIN: Self = unsafe { $ty::new_unchecked(0) };
80            #[doc = concat!("The largest value that can be represented by this positive integer type, equal to [`", stringify!($base), "::MAX`].")]
81            pub const MAX: Self = unsafe { $ty::new_unchecked(<$base>::MAX) };
82            #[doc = concat!("Creates a `", stringify!($ty), "` if the given value is positive.")]
83            pub const fn new(value: $base) -> Option<Self> {
84                if value < 0 {
85                    return None;
86                }
87                unsafe { Some(core::mem::transmute::<$base, Self>(value)) }
88            }
89            #[doc = concat!("Creates a `", stringify!($ty), "` without checking whether the value is positive.")]
90            /// This results in undefined behaviour if the value is negative.
91            ///
92            /// # Safety
93            ///
94            /// The value must not be negative.
95            #[inline]
96            pub const unsafe fn new_unchecked(value: $base) -> Self {
97                debug_assert!(value >= 0);
98                core::mem::transmute::<$base, Self>(value)
99            }
100            /// Returns the contained value as a primitive type.
101            #[inline]
102            pub const fn get(self) -> $base {
103                unsafe {
104                    let n = core::mem::transmute::<Self, $base>(self);
105                    core::hint::assert_unchecked(n >= 0);
106                    n
107                }
108            }
109            /// Returns the number of zeros in the binary representation of `self`.
110            #[inline]
111            pub const fn count_zeros(self) -> u32 {
112                self.get().count_zeros()
113            }
114            /// Returns the number of ones in the binary representation of `self`.
115            #[inline]
116            pub const fn count_ones(self) -> u32 {
117                self.get().count_ones()
118            }
119            /// Returns the number of leading zeros in the binary representation of `self`.
120            #[inline]
121            pub const fn leading_zeros(self) -> u32 {
122                self.get().leading_zeros()
123            }
124            /// Returns the number of trailing zeros in the binary representation of `self`.
125            #[inline]
126            pub const fn trailing_zeros(self) -> u32 {
127                self.get().trailing_zeros()
128            }
129            /// Returns `true` if and only if `self == (1 << k)` for some `k`.
130            #[inline]
131            pub const fn is_power_of_two(self) -> bool {
132                (self.get() as $uns).is_power_of_two()
133            }
134            /// Returns the base 2 logarithm of the number, rounded down.
135            ///
136            /// # Panics
137            ///
138            /// This function will panic if `self` is zero.
139            #[inline]
140            pub const fn ilog2(self) -> u32 {
141                self.get().ilog2()
142            }
143            /// Returns the base 10 logarithm of the number, rounded down.
144            ///
145            /// # Panics
146            ///
147            /// This function will panic if `self` is zero.
148            #[inline]
149            pub const fn ilog10(self) -> u32 {
150                self.get().ilog10()
151            }
152            /// Checked negation. Computes `-self`, returning `None` if `self == 0`.
153            #[inline]
154            pub const fn checked_neg(self) -> Option<$sty> {
155                $sty::new(-self.get())
156            }
157            /// Checked addition. Adds a positive integer to another positive integer.
158            /// Checks for overflow and returns [`None`] on overflow.
159            /// As a consequence, the result cannot wrap to a negative integer.
160            #[inline]
161            pub const fn checked_add(self, rhs: Self) -> Option<Self> {
162                match self.get().checked_add(rhs.get()) {
163                    Some(n) => unsafe { Some(Self::new_unchecked(n)) },
164                    None => None,
165                }
166            }
167            /// Checked subtraction. Subtracts a positive integer from another positive integer.
168            /// Returns [`None`] if the result would overflow into a negative integer.
169            #[inline]
170            pub const fn checked_sub(self, rhs: Self) -> Option<Self> {
171                Self::new(self.get() - rhs.get())
172            }
173            /// Checked multiplication.
174            /// Multiplies a positive integer by another positive integer, returning a positive result.
175            /// Returns [`None`] if the result would overflow.
176            #[inline]
177            pub const fn checked_mul(self, rhs: Self) -> Option<Self> {
178                match self.get().checked_mul(rhs.get()) {
179                    Some(n) => unsafe { Some(Self::new_unchecked(n)) },
180                    None => None,
181                }
182            }
183            /// Checked division.
184            /// Divides a positive integer by another positive integer, returning the positive quotient.
185            /// Returns [`None`] if `rhs == 0`.
186            #[inline]
187            pub const fn checked_div(self, rhs: Self) -> Option<Self> {
188                match self.get().checked_div(rhs.get()) {
189                    Some(n) => unsafe { Some(Self::new_unchecked(n)) },
190                    None => None,
191                }
192            }
193            /// Checked remainder.
194            /// Divides a positive integer by another positive integer, returning the positive
195            /// remainder.
196            /// Returns [`None`] if `rhs == 0`.
197            #[inline]
198            pub const fn checked_rem(self, rhs: Self) -> Option<Self> {
199                match self.get().checked_rem(rhs.get()) {
200                    Some(n) => unsafe { Some(Self::new_unchecked(n)) },
201                    None => None,
202                }
203            }
204            /// Checked division by unsigned.
205            /// Divides a positive integer by an unsigned integer, returning the positive quotient.
206            /// Returns [`None`] if `rhs == 0`.
207            #[inline]
208            pub const fn checked_div_unsigned(self, rhs: $uns) -> Option<Self> {
209                match (self.get() as $uns).checked_div(rhs) {
210                    Some(n) => unsafe { Some(Self::new_unchecked(n as $base)) },
211                    None => None,
212                }
213            }
214            /// Checked remainder of unsigned.
215            /// Divides a positive integer by an unsigned integer, returning the positive remainder.
216            /// Returns [`None`] if `rhs == 0`.
217            #[inline]
218            pub const fn checked_rem_unsigned(self, rhs: $uns) -> Option<Self> {
219                match (self.get() as $uns).checked_rem(rhs) {
220                    Some(n) => unsafe { Some(Self::new_unchecked(n as $base)) },
221                    None => None,
222                }
223            }
224            /// Checked integer exponentiation.
225            /// Raises positive value to an integer power.
226            /// Checks for overflow and returns [`None`] on overflow.
227            /// As a consequence, the result cannot wrap to a negative integer.
228            #[inline]
229            pub const fn checked_pow(self, rhs: u32) -> Option<Self> {
230                match self.get().checked_pow(rhs) {
231                    Some(n) => unsafe { Some(Self::new_unchecked(n)) },
232                    None => None,
233                }
234            }
235            /// Returns the smallest power of two greater than or equal to `self`.
236            /// Checks for overflow and returns [`None`]
237            /// if the next power of two is greater than the type’s maximum value.
238            /// As a consequence, the result cannot wrap to a negative integer.
239            #[inline]
240            pub const fn checked_next_power_of_two(self) -> Option<Self> {
241                Self::new((self.get() as $uns).next_power_of_two() as $base)
242            }
243            /// Returns the base 2 logarithm of the number, rounded down.
244            ///
245            /// Returns `None` if the number is zero.
246            #[inline]
247            pub const fn checked_ilog2(self) -> Option<u32> {
248                self.get().checked_ilog2()
249            }
250            /// Returns the base 10 logarithm of the number, rounded down.
251            ///
252            /// Returns `None` if the number is zero.
253            #[inline]
254            pub const fn checked_ilog10(self) -> Option<u32> {
255                self.get().checked_ilog10()
256            }
257            /// Saturating addition. Adds a positive integer to another positive integer.
258            #[doc = concat!("Returns [`", stringify!($ty), "::MAX`] on overflow.")]
259            #[inline]
260            pub const fn saturating_add(self, rhs: Self) -> Self {
261                let n = self.get().saturating_add(rhs.get());
262                unsafe { Self::new_unchecked(n) }
263            }
264            /// Saturating subtraction. Subtracts a positive integer from another positive integer.
265            /// Returns 0 if the result would overflow into a negative integer.
266            #[inline]
267            pub const fn saturating_sub(self, rhs: Self) -> Self {
268                match Self::new(self.get() - rhs.get()) {
269                    Some(n) => n,
270                    None => Self::MIN
271                }
272            }
273            /// Saturating multiplication.
274            /// Multiplies a positive integer by another positive integer, returning a positive result.
275            #[doc = concat!("Returns [`", stringify!($ty), "::MAX`] on overflow.")]
276            #[inline]
277            pub const fn saturating_mul(self, rhs: Self) -> Self {
278                let n = self.get().saturating_mul(rhs.get());
279                unsafe { Self::new_unchecked(n) }
280            }
281            /// Saturating integer exponentiation.
282            /// Raises positive value to an integer power.
283            #[doc = concat!("Returns [`", stringify!($ty), "::MAX`] on overflow.")]
284            #[inline]
285            pub const fn saturating_pow(self, rhs: u32) -> Self {
286                let n = self.get().saturating_pow(rhs);
287                unsafe { Self::new_unchecked(n) }
288            }
289        }
290
291        impl Default for $ty {
292            #[inline]
293            fn default() -> Self {
294                Self::MIN
295            }
296        }
297
298        impl PartialEq for $ty {
299            #[inline]
300            fn eq(&self, rhs: &Self) -> bool {
301                self.get().eq(&rhs.get())
302            }
303        }
304
305        impl PartialOrd for $ty {
306            fn partial_cmp(&self, rhs: &Self) -> Option<core::cmp::Ordering> {
307                Some(self.cmp(rhs))
308            }
309        }
310
311        impl Ord for $ty {
312            fn cmp(&self, rhs: &Self) -> core::cmp::Ordering {
313                self.get().cmp(&rhs.get())
314            }
315        }
316
317        impl Eq for $ty {}
318
319        impl core::str::FromStr for $ty {
320            type Err = core::num::IntErrorKind;
321            #[inline]
322            fn from_str(s: &str) -> Result<Self, Self::Err> {
323                let n = s.parse::<$uns>().map_err(|e| e.kind().clone())?;
324                Self::new(n as $base).ok_or_else(|| core::num::IntErrorKind::PosOverflow)
325            }
326        }
327
328        impl core::hash::Hash for $ty {
329            #[inline]
330            fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
331                self.get().hash(state);
332            }
333        }
334
335        impl core::ops::Div for $ty {
336            type Output = Self;
337            fn div(self, rhs: Self) -> Self::Output {
338                unsafe { Self::new_unchecked(self.get().div(rhs.get())) }
339            }
340        }
341        impl core::ops::DivAssign for $ty {
342            fn div_assign(&mut self, rhs: Self) {
343                *self = core::ops::Div::div(*self, rhs);
344            }
345        }
346
347        impl core::ops::Rem for $ty {
348            type Output = Self;
349            fn rem(self, rhs: Self) -> Self::Output {
350                unsafe { Self::new_unchecked(self.get().rem(rhs.get())) }
351            }
352        }
353        impl core::ops::RemAssign for $ty {
354            fn rem_assign(&mut self, rhs: Self) {
355                *self = core::ops::Rem::rem(*self, rhs);
356            }
357        }
358
359        impl core::ops::Div<$uns> for $ty {
360            type Output = Self;
361            fn div(self, rhs: $uns) -> Self::Output {
362                unsafe { Self::new_unchecked((self.get() as $uns).div(rhs) as $base) }
363            }
364        }
365        impl core::ops::DivAssign<$uns> for $ty {
366            fn div_assign(&mut self, rhs: $uns) {
367                *self = core::ops::Div::div(*self, rhs);
368            }
369        }
370
371        impl core::ops::Rem<$uns> for $ty {
372            type Output = Self;
373            fn rem(self, rhs: $uns) -> Self::Output {
374                unsafe { Self::new_unchecked((self.get() as $uns).rem(rhs) as $base) }
375            }
376        }
377        impl core::ops::RemAssign<$uns> for $ty {
378            fn rem_assign(&mut self, rhs: $uns) {
379                *self = core::ops::Rem::rem(*self, rhs);
380            }
381        }
382
383        impl core::ops::BitAnd<$base> for $ty {
384            type Output = Self;
385            #[inline]
386            fn bitand(self, rhs: $base) -> Self::Output {
387                unsafe { Self::new_unchecked(self.get().bitand(rhs)) }
388            }
389        }
390        impl core::ops::BitAndAssign<$base> for $ty {
391            #[inline]
392            fn bitand_assign(&mut self, rhs: $base) {
393                *self = core::ops::BitAnd::bitand(*self, rhs);
394            }
395        }
396
397        impl core::ops::BitAnd<$ty> for $base {
398            type Output = $ty;
399            #[inline]
400            fn bitand(self, rhs: $ty) -> Self::Output {
401                unsafe { $ty::new_unchecked(self.bitand(rhs.get())) }
402            }
403        }
404
405        impl_bit_op! { BitOr::bitor, BitOrAssign::bitor_assign for $ty }
406        impl_bit_op! { BitAnd::bitand, BitAndAssign::bitand_assign for $ty }
407        impl_bit_op! { BitXor::bitxor, BitXorAssign::bitxor_assign for $ty }
408        impl_fmt! { Display, Debug, Binary, Octal, LowerHex, UpperHex => $ty }
409    };
410}
411
412macro_rules! impl_negative {
413    ($(#[$attr:meta])* $ty:ident, $pty:ident, $d:tt $mac:ident, $base:ty, $uns:ty) => {
414
415        #[doc = concat!("Creates a [`", stringify!($ty), "`] checked at compile time.")]
416        ///
417        #[doc = concat!("This macro takes a single argument that must be a negative [`", stringify!($base), "`].")]
418        /// Positive values will cause a compile error.
419        ///
420        /// ```rust
421        #[doc = concat!("use sign_bound::{", stringify!($ty), ", ", stringify!($mac), "};")]
422        ///
423        #[doc = concat!("let val: ", stringify!($ty), " = ", stringify!($mac), "!(-123);")]
424        /// ```
425        #[macro_export]
426        macro_rules! $mac {
427            ($e:expr $d(,)?) => {
428                const {
429                    match $crate::$ty::new($e) {
430                        ::core::option::Option::Some(e) => e,
431                        _ => panic!(concat!(stringify!($base), " out of range for ", stringify!($ty))),
432                    }
433                }
434            };
435        }
436
437        /// A signed value that is known to be negative.
438        ///
439        /// This enables some memory layout optimization.
440        #[doc = concat!("For example, `Option<", stringify!($ty), ">` is the same size as [`", stringify!($base), "`].")]
441        #[derive(Copy, Clone)]
442        $(#[$attr])*
443        #[repr(C)]
444        pub struct $ty {
445            #[cfg(target_endian = "big")]
446            _hi: NegativeHighByte,
447            _buf: [u8; size_of::<$base>() - 1],
448            #[cfg(target_endian = "little")]
449            _hi: NegativeHighByte,
450        }
451
452        impl $ty {
453            /// The size of this negative integer type in bits.
454            ///
455            #[doc = concat!("This value is equal to [`", stringify!($base), "::BITS`].")]
456            pub const BITS: u32 = <$base>::BITS;
457            #[doc = concat!("The smallest value that can be represented by this negative integer type, equal to [`", stringify!($base), "::MIN`].")]
458            pub const MIN: Self = unsafe { $ty::new_unchecked(<$base>::MIN) };
459            /// The largest value that can be represented by this negative integer type, -1.
460            pub const MAX: Self = unsafe { $ty::new_unchecked(-1) };
461            #[doc = concat!("Creates a `", stringify!($ty), "` if the given value is negative.")]
462            pub const fn new(value: $base) -> Option<Self> {
463                if value >= 0 {
464                    return None;
465                }
466                unsafe { Some(core::mem::transmute::<$base, Self>(value)) }
467            }
468            #[doc = concat!("Creates a `", stringify!($ty), "` without checking whether the value is negative.")]
469            /// This results in undefined behaviour if the value is positive.
470            ///
471            /// # Safety
472            ///
473            /// The value must not be positive.
474            #[inline]
475            pub const unsafe fn new_unchecked(value: $base) -> Self {
476                debug_assert!(value < 0);
477                core::mem::transmute::<$base, Self>(value)
478            }
479            /// Returns the contained value as a primitive type.
480            #[inline]
481            pub const fn get(self) -> $base {
482                unsafe {
483                    let n = core::mem::transmute::<Self, $base>(self);
484                    core::hint::assert_unchecked(n < 0);
485                    n
486                }
487            }
488            /// Returns the number of zeros in the binary representation of `self`.
489            #[inline]
490            pub const fn count_zeros(self) -> u32 {
491                self.get().count_zeros()
492            }
493            /// Returns the number of ones in the binary representation of `self`.
494            #[inline]
495            pub const fn count_ones(self) -> u32 {
496                self.get().count_ones()
497            }
498            /// Returns the number of leading zeros in the binary representation of `self`.
499            ///
500            /// Since the value is guaranteed to be negative, this function always returns 0.
501            #[inline]
502            pub const fn leading_zeros(self) -> u32 {
503                0
504            }
505            /// Returns the number of trailing zeros in the binary representation of `self`.
506            ///
507            /// On many architectures, this function can perform better than `trailing_zeros()` on
508            /// the underlying integer type, as special handling of zero can be avoided.
509            #[inline]
510            pub const fn trailing_zeros(self) -> u32 {
511                self.get().trailing_zeros()
512            }
513            /// Checked absolute value.
514            /// Computes `-self`, returning [`None`] if <code>self == [MIN][Self::MIN]</code>.
515            #[inline]
516            pub const fn checked_abs(self) -> Option<$pty> {
517                match self.get().checked_abs() {
518                    Some(n) => unsafe { Some($pty::new_unchecked(n)) },
519                    None => None,
520                }
521            }
522            /// Checked negation.
523            /// Computes `-self`, returning [`None`] if <code>self == [MIN][Self::MIN]</code>.
524            #[inline]
525            pub const fn checked_neg(self) -> Option<$pty> {
526                match self.get().checked_neg() {
527                    Some(n) => unsafe { Some($pty::new_unchecked(n)) },
528                    None => None,
529                }
530            }
531            /// Checked addition. Adds a negative integer to another negative integer.
532            /// Checks for overflow and returns [`None`] on overflow.
533            /// As a consequence, the result cannot wrap to positive integers.
534            #[inline]
535            pub const fn checked_add(self, rhs: Self) -> Option<Self> {
536                match self.get().checked_add(rhs.get()) {
537                    Some(n) => unsafe { Some(Self::new_unchecked(n)) },
538                    None => None,
539                }
540            }
541            /// Checked subtraction. Subtracts a negative integer from another negative integer.
542            /// Returns [`None`] if the result would overflow into a positive integer.
543            #[inline]
544            pub const fn checked_sub(self, rhs: Self) -> Option<Self> {
545                Self::new(self.get() - rhs.get())
546            }
547            /// Checked multiplication.
548            /// Multiplies a negative integer by another negative integer, returning a positive result.
549            /// Returns [`None`] if the result would overflow.
550            #[inline]
551            pub const fn checked_mul(self, rhs: Self) -> Option<$pty> {
552                match self.get().checked_mul(rhs.get()) {
553                    Some(n) => unsafe { Some($pty::new_unchecked(n)) },
554                    None => None,
555                }
556            }
557            /// Checked sign-preserving multiplication. Multiplies a negative integer by a positive
558            /// integer, returning a negative result.
559            /// Returns [`None`] if `rhs == 0` or the result would overflow.
560            #[inline]
561            pub const fn checked_mul_positive(self, rhs: $pty) -> Option<Self> {
562                match self.get().checked_mul(rhs.get()) {
563                    Some(n) => Self::new(n),
564                    None => None,
565                }
566            }
567            /// Checked division.
568            /// Divides a negative integer by another negative integer, returning the positive quotient.
569            /// Returns [`None`] if the result would overflow.
570            ///
571            /// The only case where such an overflow can occur is when one divides
572            /// <code>[MIN][Self::MIN] / -1</code>; this is equivalent to
573            /// <code>-[MIN][Self::MIN]</code>, a positive value that is too large to represent
574            #[doc = concat!("as a [`", stringify!($pty), "`].")]
575            #[inline]
576            pub const fn checked_div(self, rhs: Self) -> Option<$pty> {
577                match self.get().checked_div(rhs.get()) {
578                    Some(n) => unsafe { Some($pty::new_unchecked(n)) },
579                    None => None,
580                }
581            }
582            /// Checked Euclidean division.
583            #[doc = concat!("Calculates the [Euclidean quotient](", stringify!($base), "::div_euclid)")]
584            /// of two negative integers, returning the positive result.
585            /// Returns [`None`] if the result would overflow.
586            ///
587            /// The only case where such an overflow can occur is when one divides
588            /// <code>[MIN][Self::MIN] / -1</code>; this is equivalent to
589            /// <code>-[MIN][Self::MIN]</code>, a positive value that is too large to represent
590            #[doc = concat!("as a [`", stringify!($pty), "`].")]
591            #[inline]
592            pub const fn checked_div_euclid(self, rhs: Self) -> Option<$pty> {
593                match self.get().checked_div_euclid(rhs.get()) {
594                    Some(n) => unsafe { Some($pty::new_unchecked(n)) },
595                    None => None,
596                }
597            }
598            /// Checked Euclidean remainder.
599            #[doc = concat!("Calculates the [Euclidean remainder](", stringify!($base), "::rem_euclid)")]
600            /// of a negative integer and any signed integer, returning the positive result.
601            /// Returns [`None`] if `rhs == 0` or the result would overflow.
602            ///
603            /// The only case where such an overflow can occur is when one divides
604            /// <code>[MIN][Self::MIN] / -1</code>; this is equivalent to
605            /// <code>-[MIN][Self::MIN]</code>, a positive value that is too large to represent
606            #[doc = concat!("as a [`", stringify!($pty), "`].")]
607            #[inline]
608            pub const fn checked_rem_euclid(self, rhs: $base) -> Option<$pty> {
609                match self.get().checked_rem_euclid(rhs) {
610                    Some(n) => unsafe { Some($pty::new_unchecked(n)) },
611                    None => None,
612                }
613            }
614            /// Saturating absolute value.
615            /// Computes `-self`, returning
616            #[doc = concat!("[`", stringify!($pty), "::MAX`]")]
617            /// if <code>self == [MIN][Self::MIN]</code>.
618            #[inline]
619            pub const fn saturating_abs(self) -> $pty {
620                let n = self.get().saturating_abs();
621                unsafe { $pty::new_unchecked(n) }
622            }
623            /// Saturating negation.
624            /// Computes `-self`, returning
625            #[doc = concat!("[`", stringify!($pty), "::MAX`]")]
626            /// if <code>self == [MIN][Self::MIN]</code>.
627            #[inline]
628            pub const fn saturating_neg(self) -> $pty {
629                let n = self.get().saturating_neg();
630                unsafe { $pty::new_unchecked(n) }
631            }
632            /// Saturating addition. Adds a negative integer to another negative integer.
633            #[doc = concat!("Returns [`", stringify!($ty), "::MIN`] on overflow.")]
634            #[inline]
635            pub const fn saturating_add(self, rhs: Self) -> Self {
636                let n = self.get().saturating_add(rhs.get());
637                unsafe { Self::new_unchecked(n) }
638            }
639            /// Saturating subtraction. Subtracts a negative integer from another negative integer.
640            /// Returns -1 if the result would overflow into a positive integer.
641            #[inline]
642            pub const fn saturating_sub(self, rhs: Self) -> Self {
643                match Self::new(self.get() - rhs.get()) {
644                    Some(n) => n,
645                    None => Self::MAX
646                }
647            }
648            /// Saturating multiplication.
649            /// Multiplies a negative integer by another negative integer, returning a positive result.
650            #[doc = concat!("Returns [`", stringify!($pty), "::MAX`] on overflow.")]
651            #[inline]
652            pub const fn saturating_mul(self, rhs: Self) -> $pty {
653                let n = self.get().saturating_mul(rhs.get());
654                unsafe { $pty::new_unchecked(n) }
655            }
656            /// Saturating sign-preserving multiplication.
657            /// Multiplies a negative integer by a positive integer, returning a negative result.
658            /// Returns -1 if `rhs == 0`.
659            #[doc = concat!("Returns [`", stringify!($ty), "::MIN`] on overflow.")]
660            #[inline]
661            pub const fn saturating_mul_positive(self, rhs: $pty) -> Self {
662                match Self::new(self.get().saturating_mul(rhs.get())) {
663                    Some(n) => n,
664                    None => Self::MAX,
665                }
666            }
667        }
668
669        impl PartialEq for $ty {
670            #[inline]
671            fn eq(&self, rhs: &Self) -> bool {
672                self.get().eq(&rhs.get())
673            }
674        }
675
676        impl PartialOrd for $ty {
677            fn partial_cmp(&self, rhs: &Self) -> Option<core::cmp::Ordering> {
678                Some(self.cmp(rhs))
679            }
680        }
681
682        impl Ord for $ty {
683            fn cmp(&self, rhs: &Self) -> core::cmp::Ordering {
684                self.get().cmp(&rhs.get())
685            }
686        }
687
688        impl Eq for $ty {}
689
690        impl core::str::FromStr for $ty {
691            type Err = core::num::IntErrorKind;
692            #[inline]
693            fn from_str(s: &str) -> Result<Self, Self::Err> {
694                let n = s.parse::<$base>().map_err(|e| e.kind().clone())?;
695                Self::new(n).ok_or_else(|| core::num::IntErrorKind::PosOverflow)
696            }
697        }
698
699        impl core::hash::Hash for $ty {
700            #[inline]
701            fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
702                self.get().hash(state);
703            }
704        }
705
706        impl core::ops::BitOr<$base> for $ty {
707            type Output = Self;
708            #[inline]
709            fn bitor(self, rhs: $base) -> Self::Output {
710                unsafe { Self::new_unchecked(self.get().bitor(rhs)) }
711            }
712        }
713        impl core::ops::BitOrAssign<$base> for $ty {
714            #[inline]
715            fn bitor_assign(&mut self, rhs: $base) {
716                *self = core::ops::BitOr::bitor(*self, rhs);
717            }
718        }
719
720        impl core::ops::BitOr<$ty> for $base {
721            type Output = $ty;
722            #[inline]
723            fn bitor(self, rhs: $ty) -> Self::Output {
724                unsafe { $ty::new_unchecked(self.bitor(rhs.get())) }
725            }
726        }
727
728        impl core::ops::BitOr<$ty> for $pty {
729            type Output = $ty;
730            #[inline]
731            fn bitor(self, rhs: $ty) -> Self::Output {
732                unsafe { $ty::new_unchecked(self.get().bitor(rhs.get())) }
733            }
734        }
735        impl core::ops::BitOr<$pty> for $ty {
736            type Output = Self;
737            #[inline]
738            fn bitor(self, rhs: $pty) -> Self::Output {
739                unsafe { $ty::new_unchecked(self.get().bitor(rhs.get())) }
740            }
741        }
742        impl core::ops::BitOrAssign<$pty> for $ty {
743            #[inline]
744            fn bitor_assign(&mut self, rhs: $pty) {
745                *self = core::ops::BitOr::bitor(*self, rhs);
746            }
747        }
748
749        impl core::ops::BitAnd<$pty> for $ty {
750            type Output = $pty;
751            #[inline]
752            fn bitand(self, rhs: $pty) -> Self::Output {
753                unsafe { $pty::new_unchecked(self.get().bitand(rhs.get())) }
754            }
755        }
756        impl core::ops::BitAnd<$ty> for $pty {
757            type Output = Self;
758            #[inline]
759            fn bitand(self, rhs: $ty) -> Self::Output {
760                unsafe { Self::new_unchecked(self.get().bitand(rhs.get())) }
761            }
762        }
763        impl core::ops::BitAndAssign<$ty> for $pty {
764            #[inline]
765            fn bitand_assign(&mut self, rhs: $ty) {
766                *self = core::ops::BitAnd::bitand(*self, rhs);
767            }
768        }
769
770        impl core::ops::BitXor<$pty> for $ty {
771            type Output = Self;
772            #[inline]
773            fn bitxor(self, rhs: $pty) -> Self::Output {
774                unsafe { Self::new_unchecked(self.get().bitxor(rhs.get())) }
775            }
776        }
777        impl core::ops::BitXorAssign<$pty> for $ty {
778            #[inline]
779            fn bitxor_assign(&mut self, rhs: $pty) {
780                *self = core::ops::BitXor::bitxor(*self, rhs);
781            }
782        }
783        impl core::ops::BitXor<$ty> for $pty {
784            type Output = $ty;
785            #[inline]
786            fn bitxor(self, rhs: $ty) -> Self::Output {
787                unsafe { $ty::new_unchecked(self.get().bitxor(rhs.get())) }
788            }
789        }
790        impl core::ops::BitXor for $ty {
791            type Output = $pty;
792            #[inline]
793            fn bitxor(self, rhs: Self) -> Self::Output {
794                unsafe { $pty::new_unchecked(self.get().bitxor(rhs.get())) }
795            }
796        }
797
798        impl core::ops::Not for $ty {
799            type Output = $pty;
800            fn not(self) -> Self::Output {
801                unsafe { $pty::new_unchecked(self.get().not()) }
802            }
803        }
804        impl core::ops::Not for $pty {
805            type Output = $ty;
806            fn not(self) -> Self::Output {
807                unsafe { $ty::new_unchecked(self.get().not()) }
808            }
809        }
810
811        impl_fmt! { Display, Debug, Binary, Octal, LowerHex, UpperHex => $ty }
812        impl_bit_op! { BitOr::bitor, BitOrAssign::bitor_assign for $ty }
813        impl_bit_op! { BitAnd::bitand, BitAndAssign::bitand_assign for $ty }
814    };
815}
816
817macro_rules! impl_fmt {
818    (=> $ty:ty) => {};
819    ($trait:ident $(, $rest:ident)* => $ty:ty) => {
820        impl core::fmt::$trait for $ty {
821            #[inline]
822            fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
823                core::fmt::$trait::fmt(&self.get(), f)
824            }
825        }
826        impl_fmt! { $($rest),* => $ty }
827    };
828}
829
830macro_rules! impl_from {
831    (=> $ty:ty) => {};
832    ($from:ty $(, $rest:ty)* => $ty:ty) => {
833        impl From<$from> for $ty {
834            #[inline]
835            fn from(value: $from) -> Self {
836                unsafe { Self::new_unchecked(value as _) }
837            }
838        }
839        impl_from! { $($rest),* => $ty }
840    };
841}
842
843macro_rules! impl_from_get {
844    ($ty:ty =>) => {};
845    ($ty:ty => $from:ty $(, $rest:ty)*) => {
846        impl From<$ty> for $from {
847            #[inline]
848            fn from(value: $ty) -> Self {
849                unsafe { Self::new_unchecked(value.get() as _) }
850            }
851        }
852        impl TryFrom<$from> for $ty {
853            type Error = core::num::TryFromIntError;
854            #[inline]
855            fn try_from(value: $from) -> Result<Self, Self::Error> {
856                let value = <_>::try_from(value.get())?;
857                unsafe { Ok(Self::new_unchecked(value)) }
858            }
859        }
860        impl_from_get! { $ty => $($rest),*}
861    };
862}
863
864macro_rules! impl_primitive_from {
865    ($ty:ty =>) => {};
866    ($ty:ty => $from:ty $(, $rest:ty)*) => {
867        impl From<$ty> for $from {
868            #[inline]
869            fn from(value: $ty) -> Self {
870                value.get() as _
871            }
872        }
873        impl_primitive_from! { $ty => $($rest),* }
874    };
875}
876
877macro_rules! impl_try_from {
878    ($ty:ty =>) => {};
879    ($ty:ty => $from:ty $(, $rest:ty)*) => {
880        impl TryFrom<$from> for $ty {
881            type Error = core::num::TryFromIntError;
882            #[inline]
883            fn try_from(value: $from) -> Result<Self, Self::Error> {
884                let value = <_>::try_from(value.get())?;
885                unsafe { Ok(Self::new_unchecked(value)) }
886            }
887        }
888        impl_try_from! { $ty => $($rest),*}
889    };
890}
891
892macro_rules! impl_primitive_try_from {
893    ($ty:ty =>) => {};
894    ($ty:ty => $from:ty $(, $rest:ty)*) => {
895        impl TryFrom<$ty> for $from {
896            type Error = core::num::TryFromIntError;
897            #[inline]
898            fn try_from(value: $ty) -> Result<Self, Self::Error> {
899                Self::try_from(value.get())
900            }
901        }
902        impl_primitive_try_from! { $ty => $($rest),* }
903    };
904}
905
906macro_rules! impl_positive_try_from {
907    (=> $ty:ty $(, $base:ty)* ) => {};
908    ($from:ty $(, $rest:ty)* => $ty:ty $(, $base:ty)* ) => {
909        impl TryFrom<$from> for $ty {
910            type Error = core::num::TryFromIntError;
911            #[inline]
912            fn try_from(value: $from) -> Result<Self, Self::Error> {
913                $(let value = <$base>::try_from(value)?;)*
914                unsafe { Ok(Self::new_unchecked(value as _)) }
915            }
916        }
917        impl_positive_try_from! { $($rest),* => $ty $(, $base)* }
918    };
919}
920
921macro_rules! impl_negative_try_from {
922    (=> $ty:ty, $uns:ty, $base:ty) => {};
923    ($from:ty $(, $rest:ty)* => $ty:ty, $uns:ty, $base:ty) => {
924        impl TryFrom<$from> for $ty {
925            type Error = core::num::TryFromIntError;
926            #[inline]
927            fn try_from(value: $from) -> Result<Self, Self::Error> {
928                let value = <$base>::try_from(value)?;
929                Self::new(value).ok_or_else(|| <$base>::try_from(<$uns>::MAX).unwrap_err())
930            }
931        }
932        impl_negative_try_from! { $($rest),* => $ty, $uns, $base }
933    };
934}
935macro_rules! impl_bit_op {
936    ($op:ident :: $opm:ident, $aop:ident :: $aopm:ident for $ty:ty) => {
937        impl core::ops::$op for $ty {
938            type Output = Self;
939            #[inline]
940            fn $opm(self, rhs: Self) -> Self::Output {
941                unsafe { Self::new_unchecked(self.get().$opm(rhs.get())) }
942            }
943        }
944
945        impl core::ops::$aop for $ty {
946            #[inline]
947            fn $aopm(&mut self, rhs: Self) {
948                *self = core::ops::$op::$opm(*self, rhs);
949            }
950        }
951    };
952}
953
954impl_positive! { #[repr(align(1))] PositiveI8, NegativeI8, $ positive_i8, i8, u8 }
955impl_from_get! { PositiveI8 => PositiveI16, PositiveI32, PositiveI64, PositiveIsize }
956impl_primitive_from! { PositiveI8 => u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize }
957impl_positive_try_from! { u8, u16, u32, u64, u128, usize => PositiveI8, i8 }
958impl_positive_try_from! { i16, i32, i64, i128, isize => PositiveI8, u8, i8 }
959impl_positive_try_from! { i8 => PositiveI8, u8 }
960impl_negative! { #[repr(align(1))] NegativeI8, PositiveI8, $ negative_i8, i8, u8 }
961impl_from_get! { NegativeI8 => NegativeI16, NegativeI32, NegativeI64, NegativeIsize }
962impl_primitive_from! { NegativeI8 => i8, i16, i32, i64, i128, isize }
963impl_negative_try_from! { i8, i16, i32, i64, i128, isize => NegativeI8, u8, i8 }
964
965impl_positive! { #[repr(align(2))] PositiveI16, NegativeI16, $ positive_i16, i16, u16 }
966impl_from! { u8 => PositiveI16 }
967impl_from_get! { PositiveI16 => PositiveI32, PositiveI64, PositiveIsize }
968impl_primitive_from! { PositiveI16 => u16, u32, u64, u128, usize, i16, i32, i64, i128, isize }
969impl_primitive_try_from! { PositiveI16 => u8, i8 }
970impl_positive_try_from! { u16, u32, u64, u128, usize => PositiveI16, i16 }
971impl_positive_try_from! { i8, i32, i64, i128, isize => PositiveI16, u16, i16 }
972impl_positive_try_from! { i16 => PositiveI16, u16 }
973impl_negative! { #[repr(align(2))] NegativeI16, PositiveI16, $ negative_i16, i16, u16 }
974impl_from_get! { NegativeI16 => NegativeI32, NegativeI64, NegativeIsize }
975impl_primitive_from! { NegativeI16 => i16, i32, i64, i128, isize }
976impl_primitive_try_from! { NegativeI16 => i8 }
977impl_negative_try_from! { i8, i16, i32, i64, i128, isize => NegativeI16, u16, i16 }
978
979impl_positive! { #[repr(align(4))] PositiveI32, NegativeI32, $ positive_i32, i32, u32 }
980impl_from! { u8, u16 => PositiveI32 }
981impl_from_get! { PositiveI32 => PositiveI64 }
982impl_primitive_from! { PositiveI32 => u32, u64, u128, i32, i64, i128 }
983impl_primitive_try_from! { PositiveI32 => u8, u16, usize, i8, i16, isize }
984impl_positive_try_from! { u32, u64, u128, usize => PositiveI32, i32 }
985impl_positive_try_from! { i8, i16, i64, i128, isize => PositiveI32, u32, i32 }
986impl_positive_try_from! { i32 => PositiveI32, u32 }
987impl_negative! { #[repr(align(4))] NegativeI32, PositiveI32, $ negative_i32, i32, u32 }
988impl_from_get! { NegativeI32 => NegativeI64 }
989impl_primitive_from! { NegativeI32 => i32, i64, i128 }
990impl_primitive_try_from! { NegativeI32 => i8, i16, isize }
991impl_negative_try_from! { i8, i16, i32, i64, i128, isize => NegativeI32, u32, i32 }
992
993impl_positive! { #[repr(align(8))] PositiveI64, NegativeI64, $ positive_i64, i64, u64 }
994impl_from! { u8, u16, u32 => PositiveI64 }
995impl_primitive_from! { PositiveI64 => u64, u128, i64, i128 }
996impl_primitive_try_from! { PositiveI64 => u8, u16, u32, usize, i8, i16, i32, isize }
997impl_positive_try_from! { u64, u128, usize => PositiveI64, i64 }
998impl_positive_try_from! { i8, i16, i32, i128, isize => PositiveI64, u64, i64 }
999impl_positive_try_from! { i64 => PositiveI64, u64 }
1000impl_negative! { #[repr(align(8))] NegativeI64, PositiveI64, $ negative_i64, i64, u64 }
1001impl_primitive_from! { NegativeI64 => i64, i128 }
1002impl_primitive_try_from! { NegativeI64 => i8, i16, i32, isize }
1003impl_negative_try_from! { i8, i16, i32, i64, i128, isize => NegativeI64, u64, i64 }
1004
1005#[cfg(not(any(
1006    target_pointer_width = "16",
1007    target_pointer_width = "32",
1008    target_pointer_width = "64",
1009)))]
1010compile_error!("unsupported pointer width");
1011
1012impl_positive! {
1013    #[cfg_attr(target_pointer_width = "16", repr(align(2)))]
1014    #[cfg_attr(target_pointer_width = "32", repr(align(4)))]
1015    #[cfg_attr(target_pointer_width = "64", repr(align(8)))]
1016    PositiveIsize, NegativeIsize, $ positive_isize, isize, usize
1017}
1018impl_from! { u8 => PositiveIsize }
1019impl_try_from! { PositiveIsize => PositiveI32, PositiveI64 }
1020impl_primitive_from! { PositiveIsize => usize, isize }
1021impl_primitive_try_from! { PositiveIsize => u8, u16, u32, u64, u128, i8, i16, i32, i64, i128 }
1022impl_positive_try_from! { u16, u32, u64, u128, usize => PositiveIsize, isize }
1023impl_positive_try_from! { i8, i16, i32, i64, i128 => PositiveIsize, usize, isize }
1024impl_positive_try_from! { isize => PositiveIsize, usize }
1025impl_negative! {
1026    #[cfg_attr(target_pointer_width = "16", repr(align(2)))]
1027    #[cfg_attr(target_pointer_width = "32", repr(align(4)))]
1028    #[cfg_attr(target_pointer_width = "64", repr(align(8)))]
1029    NegativeIsize, PositiveIsize, $ negative_isize, isize, usize
1030}
1031impl_try_from! { NegativeIsize => NegativeI32, NegativeI64 }
1032impl_primitive_from! { NegativeIsize => isize }
1033impl_primitive_try_from! { NegativeIsize => i8, i16, i32, i64, i128 }
1034impl_negative_try_from! { i8, i16, i32, i64, i128, isize => NegativeIsize, usize, isize }
1035
1036#[derive(Copy, Clone)]
1037#[repr(u8)]
1038enum PositiveHighByte {
1039    _0 = 0,
1040    _1 = 1,
1041    _2 = 2,
1042    _3 = 3,
1043    _4 = 4,
1044    _5 = 5,
1045    _6 = 6,
1046    _7 = 7,
1047    _8 = 8,
1048    _9 = 9,
1049    _10 = 10,
1050    _11 = 11,
1051    _12 = 12,
1052    _13 = 13,
1053    _14 = 14,
1054    _15 = 15,
1055    _16 = 16,
1056    _17 = 17,
1057    _18 = 18,
1058    _19 = 19,
1059    _20 = 20,
1060    _21 = 21,
1061    _22 = 22,
1062    _23 = 23,
1063    _24 = 24,
1064    _25 = 25,
1065    _26 = 26,
1066    _27 = 27,
1067    _28 = 28,
1068    _29 = 29,
1069    _30 = 30,
1070    _31 = 31,
1071    _32 = 32,
1072    _33 = 33,
1073    _34 = 34,
1074    _35 = 35,
1075    _36 = 36,
1076    _37 = 37,
1077    _38 = 38,
1078    _39 = 39,
1079    _40 = 40,
1080    _41 = 41,
1081    _42 = 42,
1082    _43 = 43,
1083    _44 = 44,
1084    _45 = 45,
1085    _46 = 46,
1086    _47 = 47,
1087    _48 = 48,
1088    _49 = 49,
1089    _50 = 50,
1090    _51 = 51,
1091    _52 = 52,
1092    _53 = 53,
1093    _54 = 54,
1094    _55 = 55,
1095    _56 = 56,
1096    _57 = 57,
1097    _58 = 58,
1098    _59 = 59,
1099    _60 = 60,
1100    _61 = 61,
1101    _62 = 62,
1102    _63 = 63,
1103    _64 = 64,
1104    _65 = 65,
1105    _66 = 66,
1106    _67 = 67,
1107    _68 = 68,
1108    _69 = 69,
1109    _70 = 70,
1110    _71 = 71,
1111    _72 = 72,
1112    _73 = 73,
1113    _74 = 74,
1114    _75 = 75,
1115    _76 = 76,
1116    _77 = 77,
1117    _78 = 78,
1118    _79 = 79,
1119    _80 = 80,
1120    _81 = 81,
1121    _82 = 82,
1122    _83 = 83,
1123    _84 = 84,
1124    _85 = 85,
1125    _86 = 86,
1126    _87 = 87,
1127    _88 = 88,
1128    _89 = 89,
1129    _90 = 90,
1130    _91 = 91,
1131    _92 = 92,
1132    _93 = 93,
1133    _94 = 94,
1134    _95 = 95,
1135    _96 = 96,
1136    _97 = 97,
1137    _98 = 98,
1138    _99 = 99,
1139    _100 = 100,
1140    _101 = 101,
1141    _102 = 102,
1142    _103 = 103,
1143    _104 = 104,
1144    _105 = 105,
1145    _106 = 106,
1146    _107 = 107,
1147    _108 = 108,
1148    _109 = 109,
1149    _110 = 110,
1150    _111 = 111,
1151    _112 = 112,
1152    _113 = 113,
1153    _114 = 114,
1154    _115 = 115,
1155    _116 = 116,
1156    _117 = 117,
1157    _118 = 118,
1158    _119 = 119,
1159    _120 = 120,
1160    _121 = 121,
1161    _122 = 122,
1162    _123 = 123,
1163    _124 = 124,
1164    _125 = 125,
1165    _126 = 126,
1166    _127 = 127,
1167}
1168
1169#[derive(Copy, Clone)]
1170#[repr(u8)]
1171enum NegativeHighByte {
1172    _128 = 128,
1173    _129 = 129,
1174    _130 = 130,
1175    _131 = 131,
1176    _132 = 132,
1177    _133 = 133,
1178    _134 = 134,
1179    _135 = 135,
1180    _136 = 136,
1181    _137 = 137,
1182    _138 = 138,
1183    _139 = 139,
1184    _140 = 140,
1185    _141 = 141,
1186    _142 = 142,
1187    _143 = 143,
1188    _144 = 144,
1189    _145 = 145,
1190    _146 = 146,
1191    _147 = 147,
1192    _148 = 148,
1193    _149 = 149,
1194    _150 = 150,
1195    _151 = 151,
1196    _152 = 152,
1197    _153 = 153,
1198    _154 = 154,
1199    _155 = 155,
1200    _156 = 156,
1201    _157 = 157,
1202    _158 = 158,
1203    _159 = 159,
1204    _160 = 160,
1205    _161 = 161,
1206    _162 = 162,
1207    _163 = 163,
1208    _164 = 164,
1209    _165 = 165,
1210    _166 = 166,
1211    _167 = 167,
1212    _168 = 168,
1213    _169 = 169,
1214    _170 = 170,
1215    _171 = 171,
1216    _172 = 172,
1217    _173 = 173,
1218    _174 = 174,
1219    _175 = 175,
1220    _176 = 176,
1221    _177 = 177,
1222    _178 = 178,
1223    _179 = 179,
1224    _180 = 180,
1225    _181 = 181,
1226    _182 = 182,
1227    _183 = 183,
1228    _184 = 184,
1229    _185 = 185,
1230    _186 = 186,
1231    _187 = 187,
1232    _188 = 188,
1233    _189 = 189,
1234    _190 = 190,
1235    _191 = 191,
1236    _192 = 192,
1237    _193 = 193,
1238    _194 = 194,
1239    _195 = 195,
1240    _196 = 196,
1241    _197 = 197,
1242    _198 = 198,
1243    _199 = 199,
1244    _200 = 200,
1245    _201 = 201,
1246    _202 = 202,
1247    _203 = 203,
1248    _204 = 204,
1249    _205 = 205,
1250    _206 = 206,
1251    _207 = 207,
1252    _208 = 208,
1253    _209 = 209,
1254    _210 = 210,
1255    _211 = 211,
1256    _212 = 212,
1257    _213 = 213,
1258    _214 = 214,
1259    _215 = 215,
1260    _216 = 216,
1261    _217 = 217,
1262    _218 = 218,
1263    _219 = 219,
1264    _220 = 220,
1265    _221 = 221,
1266    _222 = 222,
1267    _223 = 223,
1268    _224 = 224,
1269    _225 = 225,
1270    _226 = 226,
1271    _227 = 227,
1272    _228 = 228,
1273    _229 = 229,
1274    _230 = 230,
1275    _231 = 231,
1276    _232 = 232,
1277    _233 = 233,
1278    _234 = 234,
1279    _235 = 235,
1280    _236 = 236,
1281    _237 = 237,
1282    _238 = 238,
1283    _239 = 239,
1284    _240 = 240,
1285    _241 = 241,
1286    _242 = 242,
1287    _243 = 243,
1288    _244 = 244,
1289    _245 = 245,
1290    _246 = 246,
1291    _247 = 247,
1292    _248 = 248,
1293    _249 = 249,
1294    _250 = 250,
1295    _251 = 251,
1296    _252 = 252,
1297    _253 = 253,
1298    _254 = 254,
1299    _255 = 255,
1300}
1301
1302#[cfg(test)]
1303mod tests {
1304    use super::*;
1305    use core::ops::{
1306        BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div, DivAssign, Not, Rem,
1307        RemAssign,
1308    };
1309    use proptest::prelude::*;
1310
1311    macro_rules! test_unary {
1312        ($ty:ident, $base:ident ($range:expr) :: $($method:ident),+ $(,)?) => {
1313            proptest! {
1314                $(#[test] fn $method(n in $range) {
1315                    assert_eq!($ty::new(n).map(|n| n.$method()), Some((n as $base).$method()));
1316                })+
1317            }
1318        };
1319    }
1320
1321    macro_rules! test_unary_op {
1322        ($ty:ident, $base:ident ($range:expr) :: $($method:ident),+ $(,)?) => {
1323            proptest! {
1324                $(#[test] fn $method(n in $range) {
1325                    assert_eq!($ty::new(n).map(|n| n.$method().get()), Some((n as $base).$method()));
1326                })+
1327            }
1328        };
1329    }
1330
1331    macro_rules! test_unary_checked {
1332        ($ty:ident, $base:ident ($range:expr) :: $($method:ident),+ $(,)?) => {
1333            proptest! {
1334                $(#[test] fn $method(n in $range) {
1335                    assert_eq!($ty::new(n).and_then(|n| n.$method()), (n as $base).$method());
1336                })+
1337            }
1338        };
1339    }
1340
1341    macro_rules! test_binary {
1342        ($ty:ident, $base:ident ($range1:expr, $range2:expr) :: $($method:ident),+ $(,)?) => {
1343            proptest! {
1344                $(#[test] fn $method(a in $range1, b in $range2) {
1345                    assert_eq!(
1346                        $ty::new(a).zip($ty::new(b)).map(|(a, b)| a.$method(b)).map(|a| a.get()),
1347                        Some((a as $base).$method(b as $base)),
1348                    );
1349                })+
1350            }
1351        };
1352    }
1353
1354    macro_rules! test_binary_checked {
1355        ($ty:ident, $base:ident ($range1:expr, $range2:expr) :: $($method:ident),+ $(,)?) => {
1356            proptest! {
1357                $(#[test] fn $method(a in $range1, b in $range2) {
1358                    assert_eq!(
1359                        $ty::new(a).zip($ty::new(b)).and_then(|(a, b)| a.$method(b)).map(|a| a.get()),
1360                        (a as $base).$method(b as $base),
1361                    );
1362                })+
1363            }
1364        };
1365    }
1366
1367    macro_rules! test_assign {
1368        ($ty:ident, $base:ident ($range1:expr, $range2:expr) :: $($method:ident),+ $(,)?) => {
1369            proptest! {
1370                $(#[test] fn $method(a in $range1, b in $range2) {
1371                    let mut a1 = $ty::new(a);
1372                    let mut a2 = a;
1373                    if let Some((a, b)) = a1.as_mut().zip($ty::new(b)) {
1374                        a.$method(b);
1375                    }
1376                    a2.$method(b);
1377                    assert_eq!(a1.map(|a| a.get()), Some(a2));
1378                })+
1379            }
1380        };
1381    }
1382
1383    macro_rules! test_type {
1384        ($base:ident, $uns:ident, $pos:ident, $neg:ident) => {
1385            mod $base {
1386                use super::*;
1387                mod positive {
1388                    use super::*;
1389                    proptest! {
1390                        #[test]
1391                        fn valid(n in 0..=$base::MAX) {
1392                            assert_eq!($pos::new(n).map(|n| n.get()), Some(n));
1393                        }
1394                        #[test]
1395                        fn invalid(n in $base::MIN..-1) {
1396                            assert_eq!($pos::new(n).map(|n| n.get()), None);
1397                        }
1398                        #[test]
1399                        fn checked_neg(n in 0..=$base::MAX) {
1400                            assert_eq!(
1401                                $pos::new(n).and_then(|n| n.checked_neg()),
1402                                n.checked_neg().and_then($neg::new),
1403                            );
1404                        }
1405                        #[test]
1406                        fn checked_sub(a in 0..=$base::MAX, b in 0..=$base::MAX) {
1407                            assert_eq!(
1408                                $pos::new(a).zip($pos::new(b)).and_then(|(a, b)| a.checked_sub(b)),
1409                                a.checked_sub(b).and_then($pos::new),
1410                            );
1411                        }
1412                        #[test]
1413                        fn checked_div_unsigned(a in 0..=$base::MAX, b in 0..=$uns::MAX) {
1414                            assert_eq!(
1415                                $pos::new(a).and_then(|a| a.checked_div_unsigned(b)),
1416                                (a as $uns).checked_div(b).and_then(|n| $pos::try_from(n).ok()),
1417                            );
1418                        }
1419                        #[test]
1420                        fn checked_rem_unsigned(a in 0..=$base::MAX, b in 0..=$uns::MAX) {
1421                            assert_eq!(
1422                                $pos::new(a).and_then(|a| a.checked_rem_unsigned(b)),
1423                                (a as $uns).checked_rem(b).and_then(|n| $pos::try_from(n).ok()),
1424                            );
1425                        }
1426                        #[test]
1427                        fn checked_pow(a in 0..=$base::MAX, b in 0..u32::MAX) {
1428                            assert_eq!(
1429                                $pos::new(a).and_then(|a| a.checked_pow(b)).map(|n| n.get()),
1430                                a.checked_pow(b),
1431                            );
1432                        }
1433                        #[test]
1434                        fn checked_next_power_of_two(n in 0..=$base::MAX) {
1435                            assert_eq!(
1436                                $pos::new(n).and_then(|n| n.checked_next_power_of_two()),
1437                                (n as $uns).checked_next_power_of_two().and_then(|n| $pos::try_from(n).ok()),
1438                            );
1439                        }
1440                        #[test]
1441                        fn saturating_sub(a in 0..=$base::MAX, b in 0..=$base::MAX) {
1442                            assert_eq!(
1443                                $pos::new(a).zip($pos::new(b)).map(|(a, b)| a.saturating_sub(b)).map(|a| a.get()),
1444                                Some(a.saturating_sub(b).max(0)),
1445                            );
1446                        }
1447                        #[test]
1448                        fn saturating_pow(a in 0..=$base::MAX, b in 0..u32::MAX) {
1449                            assert_eq!(
1450                                $pos::new(a).map(|a| a.saturating_pow(b)).map(|a| a.get()),
1451                                Some((a as $base).saturating_pow(b)),
1452                            );
1453                        }
1454                    }
1455                    test_unary_op! { $pos, $base (0..=$base::MAX) :: not }
1456                    test_binary! { $pos, $base (0..=$base::MAX, 1..=$base::MAX) :: div, rem }
1457                    test_unary! { $pos, $base (0..=$base::MAX)
1458                    :: count_zeros, count_ones, leading_zeros, trailing_zeros }
1459                    test_unary! { $pos, $uns (0..=$base::MAX) :: is_power_of_two }
1460                    test_unary! { $pos, $base (1..=$base::MAX) :: ilog2, ilog10 }
1461                    test_unary_checked! { $pos, $base (1..=$base::MAX) :: checked_ilog2, checked_ilog10 }
1462                    test_binary_checked! { $pos, $base (0..=$base::MAX, 0..=$base::MAX)
1463                    :: checked_add, checked_mul, checked_div, checked_rem }
1464                    test_binary! { $pos, $base (0..=$base::MAX, 0..=$base::MAX)
1465                    :: saturating_add, saturating_mul, bitor, bitand, bitxor }
1466                    test_assign! { $pos, $base (0..=$base::MAX, 1..=$base::MAX) :: div_assign, rem_assign }
1467                    test_assign! { $pos, $base (0..=$base::MAX, 0..=$base::MAX)
1468                    :: bitor_assign, bitand_assign, bitxor_assign }
1469                }
1470                mod negative {
1471                    use super::*;
1472                    proptest! {
1473                        #[test]
1474                        fn valid(n in $base::MIN..0) {
1475                            assert_eq!($neg::new(n).map(|n| n.get()), Some(n));
1476                        }
1477                        #[test]
1478                        fn invalid(n in 0..=$base::MAX) {
1479                            assert_eq!($neg::new(n).map(|n| n.get()), None);
1480                        }
1481                        #[test]
1482                        fn checked_abs(n in $base::MIN..0) {
1483                            assert_eq!(
1484                                $neg::new(n).and_then(|n| n.checked_abs()).map(|n| n.get()),
1485                                n.checked_abs(),
1486                            );
1487                        }
1488                        #[test]
1489                        fn checked_neg(n in $base::MIN..0) {
1490                            assert_eq!(
1491                                $neg::new(n).and_then(|n| n.checked_neg()).map(|n| n.get()),
1492                                n.checked_neg(),
1493                            );
1494                        }
1495                        #[test]
1496                        fn checked_sub(a in $base::MIN..0, b in $base::MIN..0) {
1497                            assert_eq!(
1498                                $neg::new(a).zip($neg::new(b)).and_then(|(a, b)| a.checked_sub(b)),
1499                                a.checked_sub(b).and_then($neg::new),
1500                            );
1501                        }
1502                        #[test]
1503                        fn checked_mul_positive(a in $base::MIN..0, b in 0..=$base::MAX) {
1504                            assert_eq!(
1505                                $neg::new(a)
1506                                    .zip($pos::new(b))
1507                                    .and_then(|(a, b)| a.checked_mul_positive(b)),
1508                                a.checked_mul(b).and_then($neg::new),
1509                            );
1510                        }
1511                        #[test]
1512                        fn checked_rem_euclid(a in $base::MIN..0, b in $base::MIN..=$base::MAX) {
1513                            assert_eq!(
1514                                $neg::new(a).and_then(|a| a.checked_rem_euclid(b)).map(|n| n.get()),
1515                                a.checked_rem_euclid(b),
1516                            );
1517                        }
1518                        #[test]
1519                        fn saturating_abs(n in $base::MIN..0) {
1520                            assert_eq!(
1521                                $neg::new(n).map(|n| n.saturating_abs().get()),
1522                                Some(n.saturating_abs()),
1523                            );
1524                        }
1525                        #[test]
1526                        fn saturating_neg(n in $base::MIN..0) {
1527                            assert_eq!(
1528                                $neg::new(n).map(|n| n.saturating_neg().get()),
1529                                Some(n.saturating_neg()),
1530                            );
1531                        }
1532                        #[test]
1533                        fn saturating_sub(a in $base::MIN..0, b in $base::MIN..0) {
1534                            assert_eq!(
1535                                $neg::new(a)
1536                                    .zip($neg::new(b))
1537                                    .map(|(a, b)| a.saturating_sub(b).get()),
1538                                Some(a.saturating_sub(b).min(-1)),
1539                            );
1540                        }
1541                        #[test]
1542                        fn saturating_mul_positive(a in $base::MIN..0, b in 0..=$base::MAX) {
1543                            assert_eq!(
1544                                $neg::new(a)
1545                                    .zip($pos::new(b))
1546                                    .map(|(a, b)| a.saturating_mul_positive(b).get()),
1547                                Some(a.saturating_mul(b).min(-1)),
1548                            );
1549                        }
1550                        #[test]
1551                        fn bitxor_assign(a in $base::MIN..0, b in 0..=$base::MAX) {
1552                            let mut a1 = $neg::new(a);
1553                            let mut a2 = a;
1554                            if let Some((a, b)) = a1.as_mut().zip($pos::new(b)) {
1555                                a.bitxor_assign(b);
1556                            }
1557                            a2.bitxor_assign(b);
1558                            assert_eq!(a1.map(|a| a.get()), Some(a2));
1559                        }
1560                    }
1561                    test_unary_op! { $neg, $base ($base::MIN..0) :: not }
1562                    test_unary! { $neg, $base ($base::MIN..0)
1563                    :: count_zeros, count_ones, leading_zeros, trailing_zeros }
1564                    test_binary_checked! { $neg, $base ($base::MIN..0, $base::MIN..0)
1565                    :: checked_add, checked_mul, checked_div, checked_div_euclid }
1566                    test_binary! { $neg, $base ($base::MIN..0, $base::MIN..0)
1567                    :: saturating_add, saturating_mul, bitor, bitand, bitxor }
1568                    test_assign! { $neg, $base ($base::MIN..0, $base::MIN..0)
1569                    :: bitor_assign, bitand_assign }
1570                }
1571            }
1572        };
1573    }
1574    test_type! { i8, u8, PositiveI8, NegativeI8 }
1575    test_type! { i16, u16, PositiveI16, NegativeI16 }
1576    test_type! { i32, u32, PositiveI32, NegativeI32 }
1577    test_type! { i64, u64, PositiveI64, NegativeI64 }
1578    test_type! { isize, usize, PositiveIsize, NegativeIsize }
1579}