Skip to main content

amplify_num/
smallint.rs

1// SPDX-License-Identifier: Apache-2.0
2//
3// Written in 2020-2026 by Dr. Maxim Orlovsky <orlovsky@ubideco.org>
4//
5// Copyright 2024-2026 Laboratories for Ubiquitous and Deterministic Computing,
6// Institute for Distributed and Cognitive Computing (InDCS), Switzerland.
7// All rights reserved.
8//
9// Copyright (C) 2020-2026 Dr Maxim Orlovsky.
10// All rights reserved.
11//
12// Licensed under the Apache License, Version 2.0 (the "License"); you may not
13// use this file except in compliance with the License. You may obtain a copy of
14// the License at <http://www.apache.org/licenses/LICENSE-2.0>
15//
16// Unless required by applicable law or agreed to in writing, software
17// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
18// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
19// License for the specific language governing permissions and limitations under
20// the License.
21
22use core::convert::TryFrom;
23use core::ops::{
24    Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div, DivAssign,
25    Mul, MulAssign, Rem, RemAssign, Shl, ShlAssign, Shr, ShrAssign, Sub, SubAssign,
26};
27
28use crate::error::{DivError, OverflowError};
29
30macro_rules! construct_smallint {
31    ($ty:ident, $inner:ident, $to:ident, $into:ident, $bits:literal, $max:expr, $doc:meta) => {
32        #[$doc]
33        #[derive(PartialEq, Eq, Debug, Copy, Clone, Default, PartialOrd, Ord, Hash)]
34        #[cfg_attr(
35            feature = "serde",
36            derive(Serialize, Deserialize),
37            serde(crate = "serde_crate", transparent)
38        )]
39        #[allow(non_camel_case_types)]
40        pub struct $ty($inner);
41
42        impl $ty {
43            /// Bit dimension
44            pub const BITS: u32 = $bits;
45
46            /// Minimum value
47            pub const MIN: Self = Self(0);
48
49            /// Maximal value
50            pub const MAX: Self = Self($max);
51
52            /// One value
53            pub const ONE: Self = Self(1);
54
55            /// One value
56            pub const ZERO: Self = Self(0);
57
58            /// Creates a new value from a provided `value.
59            ///
60            /// Panics if the value exceeds `Self::MAX`
61            pub const fn with(value: $inner) -> Self {
62                assert!(value <= $max, "provided value exceeds Self::MAX");
63                Self(value)
64            }
65
66            /// Returns inner `u8` representation, which is always less or equal to `Self::MAX`
67            pub const fn $to(&self) -> $inner {
68                self.0 as $inner
69            }
70
71            /// Returns inner `u8` representation, which is always less or equal to `Self::MAX`
72            pub const fn $into(self) -> $inner {
73                self.0 as $inner
74            }
75        }
76
77        impl ::core::convert::TryFrom<$inner> for $ty {
78            type Error = OverflowError<$inner>;
79            #[inline]
80            fn try_from(value: $inner) -> Result<Self, Self::Error> {
81                if value > $max {
82                    Err(OverflowError { max: $max, value })
83                } else {
84                    Ok(Self(value))
85                }
86            }
87        }
88
89        impl From<$ty> for $inner {
90            #[inline]
91            fn from(val: $ty) -> Self {
92                val.0
93            }
94        }
95
96        impl AsRef<$inner> for $ty {
97            #[inline]
98            fn as_ref(&self) -> &$inner {
99                &self.0
100            }
101        }
102
103        impl ::core::str::FromStr for $ty {
104            type Err = ::core::num::ParseIntError;
105            #[inline]
106            fn from_str(s: &str) -> Result<Self, Self::Err> {
107                Self::try_from($inner::from_str(s)?).map_err(|_| u8::from_str("257").unwrap_err())
108            }
109        }
110
111        impl ::core::fmt::Display for $ty {
112            fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
113                self.0.fmt(f)
114            }
115        }
116
117        impl core::fmt::UpperHex for $ty {
118            fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
119                core::fmt::UpperHex::fmt(&self.as_ref(), f)
120            }
121        }
122
123        impl core::fmt::LowerHex for $ty {
124            fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
125                core::fmt::LowerHex::fmt(&self.as_ref(), f)
126            }
127        }
128
129        impl core::fmt::Octal for $ty {
130            fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
131                core::fmt::Octal::fmt(&self.as_ref(), f)
132            }
133        }
134
135        impl core::fmt::Binary for $ty {
136            fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
137                core::fmt::Binary::fmt(&self.as_ref(), f)
138            }
139        }
140
141        impl_op!($ty, $inner, Add, add, AddAssign, add_assign, +);
142        impl_op!($ty, $inner, Sub, sub, SubAssign, sub_assign, -);
143        impl_op!($ty, $inner, Mul, mul, MulAssign, mul_assign, *);
144        impl_op!($ty, $inner, Div, div, DivAssign, div_assign, /);
145        impl_op!($ty, $inner, Rem, rem, RemAssign, rem_assign, %);
146        impl_op!($ty, $inner, BitAnd, bitand, BitAndAssign, bitand_assign, &);
147        impl_op!($ty, $inner, BitOr, bitor, BitOrAssign, bitor_assign, |);
148        impl_op!($ty, $inner, BitXor, bitxor, BitXorAssign, bitxor_assign, ^);
149        impl_op!($ty, $inner, Shl, shl, ShlAssign, shl_assign, <<);
150        impl_op!($ty, $inner, Shr, shr, ShrAssign, shr_assign, >>);
151
152        impl $ty {
153            /// Checked integer addition. Computes `self + rhs`, returning `None` if
154            /// overflow occurred.
155            pub fn checked_add<T>(self, rhs: T) -> Option<Self> where T: Into<$inner> {
156                self.0.checked_add(rhs.into()).and_then(|val| Self::try_from(val).ok())
157            }
158            /// Saturating integer addition. Computes `self + rhs`, saturating at the
159            /// numeric bounds instead of overflowing.
160            pub fn saturating_add<T>(self, rhs: T) -> Self where T: Into<$inner> {
161                let res = self.0.saturating_add(rhs.into());
162                if res > Self::MAX.$to() {
163                    Self::MAX
164                } else {
165                    Self(res)
166                }
167            }
168            /// Calculates `self + rhs`
169            ///
170            /// Returns a tuple of the addition along with a boolean indicating whether
171            /// an arithmetic overflow would occur. If an overflow would have occurred
172            /// then the wrapped value is returned.
173            pub fn overflowing_add<T>(self, rhs: T) -> (Self, bool) where T: Into<$inner> {
174                let mut ret = self.0.overflowing_add(rhs.into());
175                if ret.0 > Self::MAX.0 {
176                    ret.0 %= Self::MAX.0;
177                    ret.1 = true;
178                }
179                (Self(ret.0), ret.1)
180            }
181            /// Wrapping (modular) addition. Computes `self + rhs`, wrapping around at
182            /// the boundary of the type.
183            pub fn wrapping_add<T>(self, rhs: T) -> Self where T: Into<$inner> {
184                #[allow(clippy::modulo_one)]
185                Self(self.0.wrapping_add(rhs.into()) % Self::MAX.0)
186            }
187
188            /// Checked integer subtraction. Computes `self - rhs`, returning `None` if
189            /// overflow occurred.
190            pub fn checked_sub<T>(self, rhs: T) -> Option<Self> where T: Into<$inner> {
191                self.0.checked_sub(rhs.into()).and_then(|val| Self::try_from(val).ok())
192            }
193            /// Saturating integer subtraction. Computes `self - rhs`, saturating at the
194            /// numeric bounds instead of overflowing.
195            pub fn saturating_sub<T>(self, rhs: T) -> Self where T: Into<$inner> {
196                let res = self.0.saturating_sub(rhs.into());
197                if res > Self::MAX.$to() {
198                    Self::MAX
199                } else {
200                    Self(res)
201                }
202            }
203            /// Calculates `self - rhs`
204            ///
205            /// Returns a tuple of the subtraction along with a boolean indicating whether
206            /// an arithmetic overflow would occur. If an overflow would have occurred
207            /// then the wrapped value is returned.
208            pub fn overflowing_sub<T>(self, rhs: T) -> (Self, bool) where T: Into<$inner> {
209                let mut ret = self.0.overflowing_sub(rhs.into());
210                if ret.0 > Self::MAX.0 {
211                    ret.0 %= Self::MAX.0;
212                    ret.1 = true;
213                }
214                (Self(ret.0), ret.1)
215            }
216            /// Wrapping (modular) subtraction. Computes `self - rhs`, wrapping around at
217            /// the boundary of the type.
218            pub fn wrapping_sub<T>(self, rhs: T) -> Self where T: Into<$inner> {
219                #[allow(clippy::modulo_one)]
220                Self(self.0.wrapping_sub(rhs.into()) % Self::MAX.0)
221            }
222
223            /// Checked integer multiplication. Computes `self * rhs`, returning `None` if
224            /// overflow occurred.
225            pub fn checked_mul<T>(self, rhs: T) -> Option<Self> where T: Into<$inner> {
226                self.0.checked_mul(rhs.into()).and_then(|val| Self::try_from(val).ok())
227            }
228            /// Saturating integer multiplication. Computes `self * rhs`, saturating at the
229            /// numeric bounds instead of overflowing.
230            pub fn saturating_mul<T>(self, rhs: T) -> Self where T: Into<$inner> {
231                let res = self.0.saturating_mul(rhs.into());
232                if res > Self::MAX.0 {
233                    Self::MAX
234                } else {
235                    Self(res)
236                }
237            }
238            /// Calculates `self * rhs`
239            ///
240            /// Returns a tuple of the multiplication along with a boolean indicating whether
241            /// an arithmetic overflow would occur. If an overflow would have occurred
242            /// then the wrapped value is returned.
243            pub fn overflowing_mul<T>(self, rhs: T) -> (Self, bool) where T: Into<$inner> {
244                let mut ret = self.0.overflowing_mul(rhs.into());
245                if ret.0 > Self::MAX.0 {
246                    ret.0 %= Self::MAX.0;
247                    ret.1 = true;
248                }
249                (Self(ret.0), ret.1)
250            }
251            /// Wrapping (modular) multiplication. Computes `self * rhs`, wrapping around at
252            /// the boundary of the type.
253            pub fn wrapping_mul<T>(self, rhs: T) -> Self where T: Into<$inner> {
254                #[allow(clippy::modulo_one)]
255                Self(self.0.wrapping_mul(rhs.into()) % Self::MAX.0)
256            }
257
258            #[inline]
259            pub fn div_rem(self, other: Self) -> Result<(Self, Self), DivError> {
260                //quotient and remainder will always be smaller than self so they're going to be in bounds
261                if other == Self(0) {
262                    return Err(DivError::ZeroDiv)
263                }
264                let quotient = self / other;
265                Ok((quotient, self - (quotient * other)))
266            }
267        }
268    };
269}
270macro_rules! impl_op {
271    ($ty:ty, $inner:ty, $op:ident, $fn:ident, $op_assign:ident, $fn_assign:ident, $sign:tt) => {
272        impl<T> $op<T> for $ty where T: Into<$inner> {
273            type Output = $ty;
274            #[inline]
275            fn $fn(self, rhs: T) -> Self::Output {
276                Self::try_from((self.0).$fn(rhs.into())).expect(stringify!(
277                    "attempt to ",
278                    $fn,
279                    " with overflow"
280                ))
281            }
282        }
283        impl<T> $op<T> for &$ty where T: Into<$inner> {
284            type Output = $ty;
285            #[inline]
286            fn $fn(self, rhs: T) -> Self::Output {
287                *self $sign rhs
288            }
289        }
290
291        impl<T> $op_assign<T> for $ty where T: Into<$inner> {
292            #[inline]
293            fn $fn_assign(&mut self, rhs: T) {
294                self.0 = (*self $sign rhs).0
295            }
296        }
297    };
298}
299
300construct_smallint!(
301    u1,
302    u8,
303    to_u8,
304    into_u8,
305    1,
306    1,
307    doc = "1-bit unsigned integer in the range `0..=1`. It can be used instead of `bool` when \
308           1-bit numeric (and not boolean) arithmetic is required"
309);
310construct_smallint!(
311    u2,
312    u8,
313    to_u8,
314    into_u8,
315    2,
316    3,
317    doc = "2-bit unsigned integer in the range `0..=3`"
318);
319construct_smallint!(
320    u3,
321    u8,
322    to_u8,
323    into_u8,
324    3,
325    7,
326    doc = "3-bit unsigned integer in the range `0..=7`"
327);
328construct_smallint!(
329    u4,
330    u8,
331    to_u8,
332    into_u8,
333    4,
334    15,
335    doc = "4-bit unsigned integer in the range `0..=15`"
336);
337construct_smallint!(
338    u5,
339    u8,
340    to_u8,
341    into_u8,
342    5,
343    31,
344    doc = "5-bit unsigned integer in the range `0..=31`"
345);
346construct_smallint!(
347    u6,
348    u8,
349    to_u8,
350    into_u8,
351    6,
352    63,
353    doc = "6-bit unsigned integer in the range `0..=63`"
354);
355construct_smallint!(
356    u7,
357    u8,
358    to_u8,
359    into_u8,
360    7,
361    127,
362    doc = "7-bit unsigned integer in the range `0..=127`"
363);
364construct_smallint!(
365    u10,
366    u16,
367    to_u16,
368    into_u16,
369    10,
370    0x3_FF,
371    doc = "10-bit unsigned integer in the range `0..=1023`"
372);
373construct_smallint!(
374    u12,
375    u16,
376    to_u16,
377    into_u16,
378    12,
379    0xF_FF,
380    doc = "12-bit unsigned integer in the range `0..=4095`"
381);
382construct_smallint!(
383    u14,
384    u16,
385    to_u16,
386    into_u16,
387    14,
388    0x3F_FF,
389    doc = "14-bit unsigned integer in the range `0..=16383`"
390);
391construct_smallint!(
392    u20,
393    u32,
394    to_u32,
395    into_u32,
396    20,
397    0xF_FF_FF,
398    doc = "20-bit unsigned integer in the range `0..=1_048_575`"
399);
400construct_smallint!(
401    u24,
402    u32,
403    to_u32,
404    into_u32,
405    24,
406    0xFF_FF_FF,
407    doc = "24-bit unsigned integer in the range `0..=16_777_215`"
408);
409construct_smallint!(
410    u40,
411    u64,
412    to_u64,
413    into_u64,
414    40,
415    0xFF_FFFF_FFFF,
416    doc = "40-bit unsigned integer in the range `0..2^40`"
417);
418construct_smallint!(
419    u48,
420    u64,
421    to_u64,
422    into_u64,
423    48,
424    0xFFFF_FFFF_FFFF,
425    doc = "48-bit unsigned integer in the range `0..2^48`"
426);
427construct_smallint!(
428    u56,
429    u64,
430    to_u64,
431    into_u64,
432    56,
433    0xFF_FFFF_FFFF_FFFF,
434    doc = "56-bit unsigned integer in the range `0..2^56`"
435);
436
437impl From<u1> for u2 {
438    fn from(value: u1) -> Self { Self(value.0) }
439}
440
441impl From<u1> for u3 {
442    fn from(value: u1) -> Self { Self(value.0) }
443}
444
445impl From<u2> for u3 {
446    fn from(value: u2) -> Self { Self(value.0) }
447}
448
449impl From<u1> for u4 {
450    fn from(value: u1) -> Self { Self(value.0) }
451}
452
453impl From<u2> for u4 {
454    fn from(value: u2) -> Self { Self(value.0) }
455}
456
457impl From<u3> for u4 {
458    fn from(value: u3) -> Self { Self(value.0) }
459}
460
461impl From<u1> for u5 {
462    fn from(value: u1) -> Self { Self(value.0) }
463}
464
465impl From<u2> for u5 {
466    fn from(value: u2) -> Self { Self(value.0) }
467}
468
469impl From<u3> for u5 {
470    fn from(value: u3) -> Self { Self(value.0) }
471}
472
473impl From<u4> for u5 {
474    fn from(value: u4) -> Self { Self(value.0) }
475}
476
477impl From<u1> for u6 {
478    fn from(value: u1) -> Self { Self(value.0) }
479}
480
481impl From<u2> for u6 {
482    fn from(value: u2) -> Self { Self(value.0) }
483}
484
485impl From<u3> for u6 {
486    fn from(value: u3) -> Self { Self(value.0) }
487}
488
489impl From<u4> for u6 {
490    fn from(value: u4) -> Self { Self(value.0) }
491}
492
493impl From<u5> for u6 {
494    fn from(value: u5) -> Self { Self(value.0) }
495}
496
497impl From<u1> for u7 {
498    fn from(value: u1) -> Self { Self(value.0) }
499}
500
501impl From<u2> for u7 {
502    fn from(value: u2) -> Self { Self(value.0) }
503}
504
505impl From<u3> for u7 {
506    fn from(value: u3) -> Self { Self(value.0) }
507}
508
509impl From<u4> for u7 {
510    fn from(value: u4) -> Self { Self(value.0) }
511}
512
513impl From<u5> for u7 {
514    fn from(value: u5) -> Self { Self(value.0) }
515}
516
517impl From<u6> for u7 {
518    fn from(value: u6) -> Self { Self(value.0) }
519}
520
521impl From<u10> for i32 {
522    fn from(val: u10) -> Self { val.0 as i32 }
523}
524
525impl From<u10> for i64 {
526    fn from(val: u10) -> Self { val.0 as i64 }
527}
528
529impl From<u10> for i128 {
530    fn from(val: u10) -> Self { val.0 as i128 }
531}
532
533impl From<u10> for isize {
534    fn from(val: u10) -> Self { val.0 as isize }
535}
536
537impl From<u10> for u64 {
538    fn from(val: u10) -> Self { val.0 as u64 }
539}
540
541impl From<u10> for u128 {
542    fn from(val: u10) -> Self { val.0 as u128 }
543}
544
545impl From<u10> for usize {
546    fn from(val: u10) -> Self { val.0 as usize }
547}
548
549impl From<u12> for i32 {
550    fn from(val: u12) -> Self { val.0 as i32 }
551}
552
553impl From<u12> for i64 {
554    fn from(val: u12) -> Self { val.0 as i64 }
555}
556
557impl From<u12> for i128 {
558    fn from(val: u12) -> Self { val.0 as i128 }
559}
560
561impl From<u12> for isize {
562    fn from(val: u12) -> Self { val.0 as isize }
563}
564
565impl From<u12> for u64 {
566    fn from(val: u12) -> Self { val.0 as u64 }
567}
568
569impl From<u12> for u128 {
570    fn from(val: u12) -> Self { val.0 as u128 }
571}
572
573impl From<u12> for usize {
574    fn from(val: u12) -> Self { val.0 as usize }
575}
576
577impl From<u14> for i32 {
578    fn from(val: u14) -> Self { val.0 as i32 }
579}
580
581impl From<u14> for i64 {
582    fn from(val: u14) -> Self { val.0 as i64 }
583}
584
585impl From<u14> for i128 {
586    fn from(val: u14) -> Self { val.0 as i128 }
587}
588
589impl From<u14> for isize {
590    fn from(val: u14) -> Self { val.0 as isize }
591}
592
593impl From<u14> for u64 {
594    fn from(val: u14) -> Self { val.0 as u64 }
595}
596
597impl From<u14> for u128 {
598    fn from(val: u14) -> Self { val.0 as u128 }
599}
600
601impl From<u14> for usize {
602    fn from(val: u14) -> Self { val.0 as usize }
603}
604
605impl From<u20> for i32 {
606    fn from(val: u20) -> Self { val.0 as i32 }
607}
608
609impl From<u20> for i64 {
610    fn from(val: u20) -> Self { val.0 as i64 }
611}
612
613impl From<u20> for i128 {
614    fn from(val: u20) -> Self { val.0 as i128 }
615}
616
617impl From<u20> for isize {
618    fn from(val: u20) -> Self { val.0 as isize }
619}
620
621impl From<u20> for u64 {
622    fn from(val: u20) -> Self { val.0 as u64 }
623}
624
625impl From<u20> for u128 {
626    fn from(val: u20) -> Self { val.0 as u128 }
627}
628
629impl From<u20> for usize {
630    fn from(val: u20) -> Self { val.0 as usize }
631}
632
633impl From<u24> for i32 {
634    fn from(val: u24) -> Self { val.0 as i32 }
635}
636
637impl From<u24> for i64 {
638    fn from(val: u24) -> Self { val.0 as i64 }
639}
640
641impl From<u24> for i128 {
642    fn from(val: u24) -> Self { val.0 as i128 }
643}
644
645impl From<u24> for isize {
646    fn from(val: u24) -> Self { val.0 as isize }
647}
648
649impl From<u24> for u64 {
650    fn from(val: u24) -> Self { val.0 as u64 }
651}
652
653impl From<u24> for u128 {
654    fn from(val: u24) -> Self { val.0 as u128 }
655}
656
657impl From<u24> for usize {
658    fn from(val: u24) -> Self { val.0 as usize }
659}
660
661impl From<u48> for i64 {
662    fn from(val: u48) -> Self { val.0 as i64 }
663}
664
665impl From<u40> for i128 {
666    fn from(val: u40) -> Self { val.0 as i128 }
667}
668
669impl From<u40> for isize {
670    fn from(val: u40) -> Self { val.0 as isize }
671}
672
673impl From<u40> for u128 {
674    fn from(val: u40) -> Self { val.0 as u128 }
675}
676
677impl From<u40> for usize {
678    fn from(val: u40) -> Self { val.0 as usize }
679}
680
681impl From<u48> for i128 {
682    fn from(val: u48) -> Self { val.0 as i128 }
683}
684
685impl From<u48> for isize {
686    fn from(val: u48) -> Self { val.0 as isize }
687}
688
689impl From<u48> for u128 {
690    fn from(val: u48) -> Self { val.0 as u128 }
691}
692
693impl From<u48> for usize {
694    fn from(val: u48) -> Self { val.0 as usize }
695}
696
697impl From<u56> for i64 {
698    fn from(val: u56) -> Self { val.0 as i64 }
699}
700
701impl From<u56> for i128 {
702    fn from(val: u56) -> Self { val.0 as i128 }
703}
704
705impl From<u56> for isize {
706    fn from(val: u56) -> Self { val.0 as isize }
707}
708
709impl From<u56> for u128 {
710    fn from(val: u56) -> Self { val.0 as u128 }
711}
712
713impl From<u56> for usize {
714    fn from(val: u56) -> Self { val.0 as usize }
715}
716
717impl u24 {
718    /// Create a native endian integer value from its representation as a byte
719    /// array in little endian.
720    pub fn from_le_bytes(bytes: [u8; 3]) -> Self {
721        let mut inner = [0u8; 4];
722        inner[..3].copy_from_slice(&bytes);
723        Self(u32::from_le_bytes(inner))
724    }
725
726    /// Return the memory representation of this integer as a byte array in
727    /// little-endian byte order.
728    pub fn to_le_bytes(self) -> [u8; 3] {
729        let mut inner = [0u8; 3];
730        inner.copy_from_slice(&self.0.to_le_bytes()[..3]);
731        inner
732    }
733
734    /// Create a native endian integer value from its representation as a byte
735    /// array in big endian.
736    pub fn from_be_bytes(bytes: [u8; 3]) -> Self {
737        let mut inner = [0u8; 4];
738        inner[1..].copy_from_slice(&bytes);
739        Self(u32::from_be_bytes(inner))
740    }
741
742    /// Return the memory representation of this integer as a byte array in
743    /// big-endian byte order.
744    pub fn to_be_bytes(self) -> [u8; 3] {
745        let mut inner = [0u8; 3];
746        inner.copy_from_slice(&self.0.to_be_bytes()[1..]);
747        inner
748    }
749
750    /// Converts into `i32` type.
751    pub const fn to_i32(&self) -> i32 { self.0 as i32 }
752
753    /// Converts into `i64` type.
754    pub const fn to_i64(&self) -> i64 { self.0 as i64 }
755
756    /// Converts into `i128` type.
757    pub const fn to_i128(&self) -> i128 { self.0 as i128 }
758
759    /// Converts into `isize` type.
760    pub const fn to_isize(&self) -> isize { self.0 as isize }
761
762    /// Converts into `u64` type.
763    pub const fn to_u64(&self) -> u64 { self.0 as u64 }
764
765    /// Converts into `i128` type.
766    pub const fn to_u128(&self) -> u128 { self.0 as u128 }
767
768    /// Converts into `usize` type.
769    pub const fn to_usize(&self) -> usize { self.0 as usize }
770
771    /// Converts into `i32` type.
772    pub const fn into_i32(self) -> i32 { self.0 as i32 }
773
774    /// Converts into `i64` type.
775    pub const fn into_i64(self) -> i64 { self.0 as i64 }
776
777    /// Converts into `i128` type.
778    pub const fn into_i128(self) -> i128 { self.0 as i128 }
779
780    /// Converts into `isize` type.
781    pub const fn into_isize(self) -> isize { self.0 as isize }
782
783    /// Converts into `u64` type.
784    pub const fn into_u64(self) -> u64 { self.0 as u64 }
785
786    /// Converts into `u128` type.
787    pub const fn into_u128(self) -> u128 { self.0 as u128 }
788
789    /// Converts into `usize` type.
790    pub const fn into_usize(self) -> usize { self.0 as usize }
791}
792
793macro_rules! impl_subu64 {
794    ($ty:ty, $len:literal) => {
795        impl $ty {
796            /// Create a native endian integer value from its representation as a byte
797            /// array in little endian.
798            pub fn from_le_bytes(bytes: [u8; $len]) -> Self {
799                let mut inner = [0u8; 8];
800                inner[..$len].copy_from_slice(&bytes);
801                Self(u64::from_le_bytes(inner))
802            }
803
804            /// Return the memory representation of this integer as a byte array in
805            /// little-endian byte order.
806            pub fn to_le_bytes(self) -> [u8; $len] {
807                let mut inner = [0u8; $len];
808                inner.copy_from_slice(&self.0.to_le_bytes()[..$len]);
809                inner
810            }
811
812            /// Create a native endian integer value from its representation as a byte
813            /// array in big endian.
814            pub fn from_be_bytes(bytes: [u8; $len]) -> Self {
815                let mut inner = [0u8; 8];
816                inner[(8 - $len)..].copy_from_slice(&bytes);
817                Self(u64::from_be_bytes(inner))
818            }
819
820            /// Return the memory representation of this integer as a byte array in
821            /// big-endian byte order.
822            pub fn to_be_bytes(self) -> [u8; $len] {
823                let mut inner = [0u8; $len];
824                inner.copy_from_slice(&self.0.to_be_bytes()[(8 - $len)..]);
825                inner
826            }
827
828            /// Converts into `i64` type.
829            pub const fn to_i64(&self) -> i64 { self.0 as i64 }
830
831            /// Converts into `i128` type.
832            pub const fn to_i128(&self) -> i128 { self.0 as i128 }
833
834            /// Converts into `isize` type.
835            pub const fn to_isize(&self) -> isize { self.0 as isize }
836
837            /// Converts into `i128` type.
838            pub const fn to_u128(&self) -> u128 { self.0 as u128 }
839
840            /// Converts into `usize` type.
841            pub const fn to_usize(&self) -> usize { self.0 as usize }
842
843            /// Converts into `i64` type.
844            pub const fn into_i64(self) -> i64 { self.0 as i64 }
845
846            /// Converts into `i128` type.
847            pub const fn into_i128(self) -> i128 { self.0 as i128 }
848
849            /// Converts into `isize` type.
850            pub const fn into_isize(self) -> isize { self.0 as isize }
851
852            /// Converts into `u128` type.
853            pub const fn into_u128(self) -> u128 { self.0 as u128 }
854
855            /// Converts into `usize` type.
856            pub const fn into_usize(self) -> usize { self.0 as usize }
857        }
858    };
859}
860impl_subu64!(u40, 5);
861impl_subu64!(u48, 6);
862impl_subu64!(u56, 7);
863
864#[cfg(test)]
865mod test {
866    use super::*;
867
868    #[test]
869    fn ubit_test() {
870        let mut u_1 = u1::try_from(u1::MAX.to_u8()).unwrap();
871        let mut u_2 = u2::try_from(u2::MAX.to_u8()).unwrap();
872        let mut u_3 = u3::try_from(u3::MAX.to_u8()).unwrap();
873        let mut u_4 = u4::try_from(u4::MAX.to_u8()).unwrap();
874        let mut u_5 = u5::try_from(u5::MAX.to_u8()).unwrap();
875        let mut u_6 = u6::try_from(u6::MAX.to_u8()).unwrap();
876        let mut u_7 = u7::try_from(u7::MAX.to_u8()).unwrap();
877        let mut u_10 = u10::try_from(u10::MAX.to_u16()).unwrap();
878        let mut u_12 = u12::try_from(u12::MAX.to_u16()).unwrap();
879        let mut u_14 = u14::try_from(u14::MAX.to_u16()).unwrap();
880        let mut u_20 = u20::try_from(u20::MAX.to_u32()).unwrap();
881        let mut u_24 = u24::try_from(u24::MAX.to_u32()).unwrap();
882
883        assert_eq!(u_1, u1::with(1));
884        assert_eq!(u_2, u2::with(3));
885        assert_eq!(u_3, u3::with(7));
886        assert_eq!(u_4, u4::with(15));
887        assert_eq!(u_5, u5::with(31));
888        assert_eq!(u_6, u6::with(63));
889        assert_eq!(u_7, u7::with(127));
890        assert_eq!(u_10, u10::with(0x3FF));
891        assert_eq!(u_12, u12::with(0xFFF));
892        assert_eq!(u_14, u14::with(0x3FFF));
893        assert_eq!(u_20, u20::with(0xF_FF_FF));
894        assert_eq!(u_24, u24::with(0xFF_FF_FF));
895
896        assert_eq!(u_1.to_u8(), 1u8);
897        assert_eq!(u_2.to_u8(), 3u8);
898        assert_eq!(u_3.to_u8(), 7u8);
899        assert_eq!(u_4.to_u8(), 15u8);
900        assert_eq!(u_5.to_u8(), 31u8);
901        assert_eq!(u_6.to_u8(), 63u8);
902        assert_eq!(u_7.to_u8(), 127u8);
903        assert_eq!(u_10.to_u16(), (1 << 10) - 1);
904        assert_eq!(u_12.to_u16(), (1 << 12) - 1);
905        assert_eq!(u_14.to_u16(), (1 << 14) - 1);
906        assert_eq!(u_20.to_u32(), (1 << 20) - 1);
907        assert_eq!(u_24.to_u32(), (1 << 24) - 1);
908
909        u_1 -= 1;
910        u_2 -= 1;
911        u_3 -= 1;
912        u_4 -= 1;
913        u_5 -= 1;
914        u_6 -= 1;
915        u_7 -= 1;
916        u_10 -= 1u16;
917        u_12 -= 1u16;
918        u_14 -= 1u16;
919        u_20 -= 1u32;
920        u_24 -= 1u32;
921
922        assert_eq!(u_1.to_u8(), 0u8);
923        assert_eq!(u_2.to_u8(), 2u8);
924        assert_eq!(u_3.to_u8(), 6u8);
925        assert_eq!(u_4.to_u8(), 14u8);
926        assert_eq!(u_5.to_u8(), 30u8);
927        assert_eq!(u_6.to_u8(), 62u8);
928        assert_eq!(u_7.to_u8(), 126u8);
929        assert_eq!(u_10.to_u16(), (1 << 10) - 2);
930        assert_eq!(u_12.to_u16(), (1 << 12) - 2);
931        assert_eq!(u_14.to_u16(), (1 << 14) - 2);
932        assert_eq!(u_20.to_u32(), (1 << 20) - 2);
933        assert_eq!(u_24.to_u32(), (1 << 24) - 2);
934
935        u_1 /= 2;
936        u_1 *= 2;
937        u_1 += 1;
938
939        u_2 /= 2;
940        u_2 *= 2;
941        u_2 += 1;
942
943        u_3 /= 2;
944        u_3 *= 2;
945        u_3 += 1;
946
947        u_4 /= 2;
948        u_4 *= 2;
949        u_4 += 1;
950
951        u_5 /= 2;
952        u_5 *= 2;
953        u_5 += 1;
954
955        u_6 /= 2;
956        u_6 *= 2;
957        u_6 += 1;
958
959        u_7 /= 2;
960        u_7 *= 2;
961        u_7 += 1;
962
963        u_10 /= 2u16;
964        u_10 *= 2u16;
965        u_10 += 1u16;
966
967        u_12 /= 2u16;
968        u_12 *= 2u16;
969        u_12 += 1u16;
970
971        u_14 /= 2u16;
972        u_14 *= 2u16;
973        u_14 += 1u16;
974
975        u_20 /= 2u32;
976        u_20 *= 2u32;
977        u_20 += 1u32;
978
979        u_24 /= 2u32;
980        u_24 *= 2u32;
981        u_24 += 1u32;
982
983        assert_eq!(u_1.to_u8(), 1u8);
984        assert_eq!(u_2.to_u8(), 3u8);
985        assert_eq!(u_3.to_u8(), 7u8);
986        assert_eq!(u_4.to_u8(), 15u8);
987        assert_eq!(u_5.to_u8(), 31u8);
988        assert_eq!(u_6.to_u8(), 63u8);
989        assert_eq!(u_7.to_u8(), 127u8);
990        assert_eq!(u_10.to_u16(), (1 << 10) - 1);
991        assert_eq!(u_12.to_u16(), (1 << 12) - 1);
992        assert_eq!(u_14.to_u16(), (1 << 14) - 1);
993        assert_eq!(u_20.to_u32(), (1 << 20) - 1);
994        assert_eq!(u_24.to_u32(), (1 << 24) - 1);
995
996        assert_eq!(u_1.to_u8() % 2, 1);
997        assert_eq!(u_2.to_u8() % 2, 1);
998        assert_eq!(u_3.to_u8() % 2, 1);
999        assert_eq!(u_4.to_u8() % 2, 1);
1000        assert_eq!(u_5.to_u8() % 2, 1);
1001        assert_eq!(u_6.to_u8() % 2, 1);
1002        assert_eq!(u_7.to_u8() % 2, 1);
1003        assert_eq!(u_10.to_u16() % 2, 1);
1004        assert_eq!(u_12.to_u16() % 2, 1);
1005        assert_eq!(u_14.to_u16() % 2, 1);
1006        assert_eq!(u_20.to_u32() % 2, 1);
1007        assert_eq!(u_24.to_u32() % 2, 1);
1008    }
1009
1010    #[test]
1011    #[should_panic(expected = "OverflowError { max: 1, value: 2 }")]
1012    fn u1_overflow_test() { u1::try_from(2).unwrap(); }
1013
1014    #[test]
1015    #[should_panic(expected = "OverflowError { max: 3, value: 4 }")]
1016    fn u2_overflow_test() { u2::try_from(4).unwrap(); }
1017
1018    #[test]
1019    #[should_panic(expected = "OverflowError { max: 7, value: 8 }")]
1020    fn u3_overflow_test() { u3::try_from(8).unwrap(); }
1021
1022    #[test]
1023    #[should_panic(expected = "OverflowError { max: 15, value: 16 }")]
1024    fn u4_overflow_test() { u4::try_from(16).unwrap(); }
1025
1026    #[test]
1027    #[should_panic(expected = "OverflowError { max: 31, value: 32 }")]
1028    fn u5_overflow_test() { u5::try_from(32).unwrap(); }
1029
1030    #[test]
1031    #[should_panic(expected = "OverflowError { max: 63, value: 64 }")]
1032    fn u6_overflow_test() { u6::try_from(64).unwrap(); }
1033
1034    #[test]
1035    #[should_panic(expected = "OverflowError { max: 127, value: 128 }")]
1036    fn u7_overflow_test() { u7::try_from(128).unwrap(); }
1037
1038    #[test]
1039    #[should_panic(expected = "OverflowError { max: 1023, value: 1024 }")]
1040    fn u10_overflow_test() { u10::try_from(1 << 10).unwrap(); }
1041
1042    #[test]
1043    #[should_panic(expected = "OverflowError { max: 4095, value: 4096 }")]
1044    fn u12_overflow_test() { u12::try_from(1 << 12).unwrap(); }
1045
1046    #[test]
1047    #[should_panic(expected = "OverflowError { max: 16383, value: 16384 }")]
1048    fn u14_overflow_test() { u14::try_from(1 << 14).unwrap(); }
1049
1050    #[test]
1051    #[should_panic(expected = "OverflowError { max: 1048575, value: 1048576 }")]
1052    fn u20_overflow_test() { u20::try_from(1 << 20).unwrap(); }
1053
1054    #[test]
1055    #[should_panic(expected = "OverflowError { max: 16777215, value: 16777216 }")]
1056    fn u24_overflow_test() { u24::try_from(1 << 24).unwrap(); }
1057
1058    #[test]
1059    fn u24_endianess() {
1060        let val: u32 = 0x00adbeef;
1061        let le = [0xef, 0xbe, 0xad];
1062        let v1 = u24::with(val);
1063        assert_eq!(v1.to_u32(), val);
1064        assert_eq!(v1.to_le_bytes(), le);
1065        let v2 = u24::from_le_bytes(le);
1066        assert_eq!(v2.to_le_bytes(), le);
1067        assert_eq!(v2, v1);
1068        assert_eq!(v2.to_u32(), v1.to_u32());
1069    }
1070
1071    #[test]
1072    fn smallint_div_rem_0() {
1073        let u_2 = u2::MAX;
1074        let u_2_2 = u2::try_from(2).unwrap();
1075        let u_2_half = (u2::MAX / 2, u2::MAX % 2);
1076        let u_2_zero = u2::ZERO;
1077
1078        assert_eq!(u2::div_rem(u_2, u_2_2), Ok(u_2_half));
1079        assert_eq!(u2::div_rem(u_2, u_2_zero), Err(DivError::ZeroDiv));
1080    }
1081
1082    #[test]
1083    fn smallint_div_rem() {
1084        let u_2 = u2::MAX;
1085        let u_2_zero = u2::ZERO;
1086        assert_eq!(u2::div_rem(u_2, u_2_zero), Err(DivError::ZeroDiv));
1087    }
1088
1089    #[test]
1090    fn fmt_test() {
1091        let u_1 = u1::MAX;
1092        let u_2 = u2::MAX;
1093        let u_3 = u3::MAX;
1094        let u_4 = u4::MAX;
1095        let u_5 = u5::MAX;
1096        let u_6 = u6::MAX;
1097        let u_7 = u7::MAX;
1098        let u_10 = u10::MAX;
1099        let u_12 = u12::MAX;
1100        let u_14 = u14::MAX;
1101        let u_20 = u20::MAX;
1102        let u_24 = u24::MAX;
1103
1104        // UpperHex
1105        assert_eq!(format!("{:X}", u_1), "1");
1106        assert_eq!(format!("{:X}", u_2), "3");
1107        assert_eq!(format!("{:X}", u_3), "7");
1108        assert_eq!(format!("{:X}", u_4), "F");
1109        assert_eq!(format!("{:X}", u_5), "1F");
1110        assert_eq!(format!("{:X}", u_6), "3F");
1111        assert_eq!(format!("{:X}", u_7), "7F");
1112        assert_eq!(format!("{:X}", u_10), "3FF");
1113        assert_eq!(format!("{:X}", u_12), "FFF");
1114        assert_eq!(format!("{:X}", u_14), "3FFF");
1115        assert_eq!(format!("{:X}", u_20), "FFFFF");
1116        assert_eq!(format!("{:X}", u_24), "FFFFFF");
1117
1118        assert_eq!(format!("{:#X}", u_1), "0x1");
1119        assert_eq!(format!("{:#X}", u_2), "0x3");
1120        assert_eq!(format!("{:#X}", u_3), "0x7");
1121        assert_eq!(format!("{:#X}", u_4), "0xF");
1122        assert_eq!(format!("{:#X}", u_5), "0x1F");
1123        assert_eq!(format!("{:#X}", u_6), "0x3F");
1124        assert_eq!(format!("{:#X}", u_7), "0x7F");
1125        assert_eq!(format!("{:#X}", u_10), "0x3FF");
1126        assert_eq!(format!("{:#X}", u_12), "0xFFF");
1127        assert_eq!(format!("{:#X}", u_14), "0x3FFF");
1128        assert_eq!(format!("{:#X}", u_20), "0xFFFFF");
1129        assert_eq!(format!("{:#X}", u_24), "0xFFFFFF");
1130
1131        // LowerHex
1132        assert_eq!(format!("{:x}", u_1), "1");
1133        assert_eq!(format!("{:x}", u_2), "3");
1134        assert_eq!(format!("{:x}", u_3), "7");
1135        assert_eq!(format!("{:x}", u_4), "f");
1136        assert_eq!(format!("{:x}", u_5), "1f");
1137        assert_eq!(format!("{:x}", u_6), "3f");
1138        assert_eq!(format!("{:x}", u_7), "7f");
1139        assert_eq!(format!("{:x}", u_10), "3ff");
1140        assert_eq!(format!("{:x}", u_12), "fff");
1141        assert_eq!(format!("{:x}", u_14), "3fff");
1142        assert_eq!(format!("{:x}", u_20), "fffff");
1143        assert_eq!(format!("{:x}", u_24), "ffffff");
1144
1145        assert_eq!(format!("{:#x}", u_1), "0x1");
1146        assert_eq!(format!("{:#x}", u_2), "0x3");
1147        assert_eq!(format!("{:#x}", u_3), "0x7");
1148        assert_eq!(format!("{:#x}", u_4), "0xf");
1149        assert_eq!(format!("{:#x}", u_5), "0x1f");
1150        assert_eq!(format!("{:#x}", u_6), "0x3f");
1151        assert_eq!(format!("{:#x}", u_7), "0x7f");
1152        assert_eq!(format!("{:#x}", u_10), "0x3ff");
1153        assert_eq!(format!("{:#x}", u_12), "0xfff");
1154        assert_eq!(format!("{:#x}", u_14), "0x3fff");
1155        assert_eq!(format!("{:#x}", u_20), "0xfffff");
1156        assert_eq!(format!("{:#x}", u_24), "0xffffff");
1157
1158        // Octal
1159        assert_eq!(format!("{:o}", u_1), "1");
1160        assert_eq!(format!("{:o}", u_2), "3");
1161        assert_eq!(format!("{:o}", u_3), "7");
1162        assert_eq!(format!("{:o}", u_4), "17");
1163        assert_eq!(format!("{:o}", u_5), "37");
1164        assert_eq!(format!("{:o}", u_6), "77");
1165        assert_eq!(format!("{:o}", u_7), "177");
1166        assert_eq!(format!("{:o}", u_10), "1777");
1167        assert_eq!(format!("{:o}", u_12), "7777");
1168        assert_eq!(format!("{:o}", u_14), "37777");
1169        assert_eq!(format!("{:o}", u_20), "3777777");
1170        assert_eq!(format!("{:o}", u_24), "77777777");
1171
1172        assert_eq!(format!("{:#o}", u_1), "0o1");
1173        assert_eq!(format!("{:#o}", u_2), "0o3");
1174        assert_eq!(format!("{:#o}", u_3), "0o7");
1175        assert_eq!(format!("{:#o}", u_4), "0o17");
1176        assert_eq!(format!("{:#o}", u_5), "0o37");
1177        assert_eq!(format!("{:#o}", u_6), "0o77");
1178        assert_eq!(format!("{:#o}", u_7), "0o177");
1179        assert_eq!(format!("{:#o}", u_10), "0o1777");
1180        assert_eq!(format!("{:#o}", u_12), "0o7777");
1181        assert_eq!(format!("{:#o}", u_14), "0o37777");
1182        assert_eq!(format!("{:#o}", u_20), "0o3777777");
1183        assert_eq!(format!("{:#o}", u_24), "0o77777777");
1184
1185        // Binary
1186        assert_eq!(format!("{:b}", u_1), "1");
1187        assert_eq!(format!("{:b}", u_2), "11");
1188        assert_eq!(format!("{:b}", u_3), "111");
1189        assert_eq!(format!("{:b}", u_4), "1111");
1190        assert_eq!(format!("{:b}", u_5), "11111");
1191        assert_eq!(format!("{:b}", u_6), "111111");
1192        assert_eq!(format!("{:b}", u_7), "1111111");
1193        assert_eq!(format!("{:b}", u_10), "1111111111");
1194        assert_eq!(format!("{:b}", u_12), "111111111111");
1195        assert_eq!(format!("{:b}", u_14), "11111111111111");
1196        assert_eq!(format!("{:b}", u_20), "11111111111111111111");
1197        assert_eq!(format!("{:b}", u_24), "111111111111111111111111");
1198
1199        assert_eq!(format!("{:#b}", u_1), "0b1");
1200        assert_eq!(format!("{:#b}", u_2), "0b11");
1201        assert_eq!(format!("{:#b}", u_3), "0b111");
1202        assert_eq!(format!("{:#b}", u_4), "0b1111");
1203        assert_eq!(format!("{:#b}", u_5), "0b11111");
1204        assert_eq!(format!("{:#b}", u_6), "0b111111");
1205        assert_eq!(format!("{:#b}", u_7), "0b1111111");
1206        assert_eq!(format!("{:#b}", u_10), "0b1111111111");
1207        assert_eq!(format!("{:#b}", u_12), "0b111111111111");
1208        assert_eq!(format!("{:#b}", u_14), "0b11111111111111");
1209        assert_eq!(format!("{:#b}", u_20), "0b11111111111111111111");
1210        assert_eq!(format!("{:#b}", u_24), "0b111111111111111111111111");
1211    }
1212}