js_int/
uint.rs

1use core::{
2    convert::TryFrom,
3    iter,
4    ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Rem, RemAssign, Sub, SubAssign},
5    str::FromStr,
6};
7
8#[cfg(feature = "serde")]
9use serde::{
10    de::{Error as _, Unexpected},
11    Deserialize, Deserializer, Serialize,
12};
13
14use crate::{
15    error::{ParseIntError, ParseIntErrorKind, TryFromIntError},
16    MAX_SAFE_INT,
17};
18
19/// The same as `MAX_SAFE_INT`, but with `u64` as the type.
20pub const MAX_SAFE_UINT: u64 = 0x001F_FFFF_FFFF_FFFF;
21
22/// An integer limited to the range of non-negative integers that can be represented exactly by an
23/// f64.
24#[derive(Clone, Copy, Default, Hash, PartialEq, Eq, PartialOrd, Ord)]
25#[cfg_attr(feature = "serde", derive(Serialize))]
26pub struct UInt(u64);
27
28impl UInt {
29    /// The smallest value that can be represented by this integer type.
30    ///
31    /// # Examples
32    ///
33    /// Basic usage:
34    ///
35    /// ```
36    /// # use js_int::{uint, UInt};
37    /// assert_eq!(UInt::MIN, uint!(0));
38    /// ```
39    pub const MIN: Self = Self(0);
40
41    /// The largest value that can be represented by this integer type.
42    ///
43    /// # Examples
44    ///
45    /// Basic usage:
46    ///
47    /// ```
48    /// # use {core::convert::TryFrom, js_int::UInt};
49    /// assert_eq!(UInt::MAX, UInt::try_from(9_007_199_254_740_991u64).unwrap());
50    /// ```
51    pub const MAX: Self = Self(MAX_SAFE_UINT);
52
53    /// Try to create a `UInt` from the provided `u64`, returning `None` if it is larger than
54    /// `MAX_SAFE_UINT`.
55    ///
56    /// This is the same as the `TryFrom<u64>` implementation for `UInt`, except that it returns
57    /// an `Option` instead of a `Result`.
58    ///
59    /// # Examples
60    ///
61    /// Basic usage:
62    ///
63    /// ```
64    /// # use js_int::UInt;
65    /// assert_eq!(UInt::new(js_int::MAX_SAFE_UINT), Some(UInt::MAX));
66    /// assert_eq!(UInt::new(js_int::MAX_SAFE_UINT + 1), None);
67    /// ```
68    #[must_use]
69    pub fn new(val: u64) -> Option<Self> {
70        if val <= MAX_SAFE_UINT {
71            Some(Self(val))
72        } else {
73            None
74        }
75    }
76
77    /// Create a `UInt` from the provided `u64`, wrapping at `MAX_SAFE_UINT`.
78    ///
79    /// # Examples
80    ///
81    /// Basic usage:
82    ///
83    /// ```
84    /// # use js_int::{uint, UInt};
85    /// assert_eq!(UInt::new_wrapping(js_int::MAX_SAFE_UINT), UInt::MAX);
86    /// assert_eq!(UInt::new_wrapping(js_int::MAX_SAFE_UINT + 1), uint!(0));
87    /// ```
88    #[must_use]
89    pub fn new_wrapping(val: u64) -> Self {
90        Self(val & MAX_SAFE_UINT)
91    }
92
93    /// Creates an `UInt` from the given `u64` capped at `MAX_SAFE_UINT`.
94    ///
95    /// # Examples
96    ///
97    /// Basic usage:
98    ///
99    /// ```
100    /// # use js_int::{uint, UInt};
101    /// assert_eq!(UInt::new_saturating(0), uint!(0));
102    /// assert_eq!(UInt::new_saturating(js_int::MAX_SAFE_UINT), UInt::MAX);
103    /// assert_eq!(UInt::new_saturating(js_int::MAX_SAFE_UINT + 1), UInt::MAX);
104    /// ```
105    #[must_use]
106    pub fn new_saturating(val: u64) -> Self {
107        if val <= MAX_SAFE_UINT {
108            Self(val)
109        } else {
110            Self::MAX
111        }
112    }
113
114    /// The constructor used for arithmetic operations
115    #[must_use]
116    fn new_(val: u64) -> Self {
117        if cfg!(debug_assertions) {
118            assert!(val <= MAX_SAFE_UINT);
119            Self(val)
120        } else {
121            Self::new_wrapping(val)
122        }
123    }
124
125    /// Helper function for mutable arithmetic operations (`+=`, `-=`, …)
126    fn assign_(&mut self, val: u64) {
127        if cfg!(debug_assertions) {
128            assert!(val <= MAX_SAFE_UINT);
129            *self = Self(val);
130        } else {
131            *self = Self::new_wrapping(val);
132        }
133    }
134
135    /// Returns the smallest value that can be represented by this integer type.
136    ///
137    /// # Examples
138    ///
139    /// Basic usage:
140    ///
141    /// ```
142    /// # use js_int::{uint, UInt};
143    /// assert_eq!(UInt::min_value(), uint!(0));
144    /// ```
145    #[must_use]
146    #[deprecated = "Use `UInt::MIN` instead."]
147    pub const fn min_value() -> Self {
148        Self(0)
149    }
150
151    /// Returns the largest value that can be represented by this integer type.
152    ///
153    /// # Examples
154    ///
155    /// Basic usage:
156    ///
157    /// ```
158    /// # use {core::convert::TryFrom, js_int::UInt};
159    /// assert_eq!(UInt::max_value(), UInt::try_from(9_007_199_254_740_991u64).unwrap());
160    /// ```
161    #[must_use]
162    #[deprecated = "Use `UInt::MAX` instead."]
163    pub const fn max_value() -> Self {
164        Self(MAX_SAFE_UINT)
165    }
166
167    /// Returns true if and only if `self == 2^k` for some `k`.
168    ///
169    /// # Examples
170    ///
171    /// Basic usage:
172    ///
173    /// ```
174    /// # use js_int::uint;
175    /// assert!(uint!(16).is_power_of_two());
176    /// assert!(!uint!(10).is_power_of_two());
177    /// ```
178    #[must_use]
179    pub fn is_power_of_two(self) -> bool {
180        self.0.is_power_of_two()
181    }
182
183    /// Returns the smallest power of two greater than or equal to `n`. If the next power of two is
184    /// greater than the type's maximum value, `None` is returned, otherwise the power of two is
185    /// wrapped in `Some`.
186    ///
187    /// # Examples
188    ///
189    /// Basic usage:
190    ///
191    /// ```
192    /// # use js_int::{uint, UInt};
193    /// assert_eq!(uint!(2).checked_next_power_of_two(), Some(uint!(2)));
194    /// assert_eq!(uint!(3).checked_next_power_of_two(), Some(uint!(4)));
195    /// assert_eq!(UInt::MAX.checked_next_power_of_two(), None);
196    /// ```
197    #[must_use]
198    pub fn checked_next_power_of_two(self) -> Option<Self> {
199        self.0.checked_next_power_of_two().and_then(Self::new)
200    }
201
202    /// Converts a string slice in a given base to an integer.
203    ///
204    /// The string is expected to be an optional `+` sign followed by digits. Leading and trailing
205    /// whitespace represent an error. Digits are a subset of these characters, depending on
206    /// `radix`:
207    ///
208    /// * `0-9`
209    /// * `a-z`
210    /// * `A-Z`
211    ///
212    /// # Panics
213    ///
214    /// This function panics if `radix` is not in the range from 2 to 36.
215    ///
216    /// # Examples
217    ///
218    /// Basic usage:
219    ///
220    /// ```
221    /// # use js_int::{uint, UInt};
222    /// assert_eq!(UInt::from_str_radix("A", 16), Ok(uint!(10)));
223    /// ```
224    pub fn from_str_radix(src: &str, radix: u32) -> Result<Self, ParseIntError> {
225        let val = u64::from_str_radix(src, radix)?;
226        if val > MAX_SAFE_UINT {
227            Err(ParseIntError { kind: ParseIntErrorKind::Overflow })
228        } else {
229            Ok(Self(val))
230        }
231    }
232
233    /// Checked integer addition. Computes `self + rhs`, returning `None` if overflow occurred.
234    ///
235    /// ```
236    /// # use js_int::{uint, UInt};
237    /// assert_eq!(
238    ///     (UInt::MAX - uint!(2)).checked_add(uint!(1)),
239    ///     Some(UInt::MAX - uint!(1))
240    /// );
241    /// assert_eq!((UInt::MAX - uint!(2)).checked_add(uint!(3)), None);
242    /// ```
243    #[must_use]
244    pub fn checked_add(self, rhs: Self) -> Option<Self> {
245        self.0.checked_add(rhs.0).and_then(Self::new)
246    }
247
248    /// Checked integer subtraction. Computes `self - rhs`, returning `None` if overflow occurred.
249    ///
250    /// # Examples
251    ///
252    /// Basic usage:
253    ///
254    /// ```
255    /// # use js_int::uint;
256    /// assert_eq!(uint!(1).checked_sub(uint!(1)), Some(uint!(0)));
257    /// assert_eq!(uint!(0).checked_sub(uint!(1)), None);
258    /// ```
259    #[must_use]
260    pub fn checked_sub(self, rhs: Self) -> Option<Self> {
261        self.0.checked_sub(rhs.0).and_then(Self::new)
262    }
263
264    /// Checked integer multiplication. Computes `self * rhs`, returning `None` if overflow
265    /// occurred.
266    ///
267    /// # Examples
268    ///
269    /// Basic usage:
270    ///
271    /// ```
272    /// # use js_int::{uint, UInt};
273    /// assert_eq!(uint!(5).checked_mul(uint!(1)), Some(uint!(5)));
274    /// assert_eq!(UInt::MAX.checked_mul(uint!(2)), None);
275    /// ```
276    #[must_use]
277    pub fn checked_mul(self, rhs: Self) -> Option<Self> {
278        self.0.checked_mul(rhs.0).and_then(Self::new)
279    }
280
281    /// Checked integer division. Computes `self / rhs`, returning `None` if `rhs == 0`.
282    ///
283    /// # Examples
284    ///
285    /// Basic usage:
286    ///
287    /// ```
288    /// # use js_int::uint;
289    /// assert_eq!(uint!(128).checked_div(uint!(2)), Some(uint!(64)));
290    /// assert_eq!(uint!(1).checked_div(uint!(0)), None);
291    /// ```
292    #[must_use]
293    pub fn checked_div(self, rhs: Self) -> Option<Self> {
294        self.0.checked_div(rhs.0).map(Self)
295    }
296
297    /// Checked integer remainder. Computes `self % rhs`, returning `None` if `rhs == 0`.
298    ///
299    /// # Examples
300    ///
301    /// Basic usage:
302    ///
303    /// ```
304    /// # use js_int::uint;
305    /// assert_eq!(uint!(5).checked_rem(uint!(2)), Some(uint!(1)));
306    /// assert_eq!(uint!(5).checked_rem(uint!(0)), None);
307    /// ```
308    #[must_use]
309    pub fn checked_rem(self, rhs: Self) -> Option<Self> {
310        self.0.checked_rem(rhs.0).map(Self)
311    }
312
313    /// Checked negation. Computes `-self`, returning None unless `self == 0`.
314    ///
315    /// Note that negating any positive integer will overflow.
316    ///
317    /// # Examples
318    ///
319    /// Basic usage:
320    ///
321    /// ```
322    /// # use js_int::uint;
323    /// assert_eq!(uint!(0).checked_neg(), Some(uint!(0)));
324    /// assert_eq!(uint!(1).checked_neg(), None);
325    /// ```
326    #[must_use]
327    pub fn checked_neg(self) -> Option<Self> {
328        self.0.checked_neg().map(Self)
329    }
330
331    /// Checked exponentiation. Computes `self.pow(exp)`, returning `None` if overflow or
332    /// underflow occurred.
333    ///
334    /// # Examples
335    ///
336    /// Basic usage:
337    ///
338    /// ```
339    /// # use js_int::{uint, UInt};
340    /// assert_eq!(uint!(0).checked_pow(2), Some(uint!(0)));
341    /// assert_eq!(uint!(8).checked_pow(2), Some(uint!(64)));
342    /// assert_eq!(uint!(1_000_000_000u32).checked_pow(2), None);
343    /// assert_eq!(UInt::MAX.checked_pow(2), None);
344    /// ```
345    #[must_use]
346    pub fn checked_pow(self, exp: u32) -> Option<Self> {
347        self.0.checked_pow(exp).and_then(Self::new)
348    }
349
350    /// Saturating integer addition. Computes `self + rhs`, saturating at the numeric bounds
351    /// instead of overflowing.
352    ///
353    /// # Examples
354    ///
355    /// Basic usage:
356    ///
357    /// ```
358    /// # use js_int::{uint, UInt};
359    /// assert_eq!(uint!(100).saturating_add(uint!(1)), uint!(101));
360    /// assert_eq!(UInt::MAX.saturating_add(uint!(1)), UInt::MAX);
361    /// ```
362    #[must_use]
363    pub fn saturating_add(self, rhs: Self) -> Self {
364        self.checked_add(rhs).unwrap_or(Self::MAX)
365    }
366
367    /// Saturating integer subtraction. Computes `self - rhs`, saturating at the numeric
368    /// bounds instead of underflowing.
369    ///
370    /// # Examples
371    ///
372    /// Basic usage:
373    ///
374    /// ```
375    /// # use js_int::uint;
376    /// assert_eq!(uint!(100).saturating_sub(uint!(1)), uint!(99));
377    /// assert_eq!(uint!(1).saturating_sub(uint!(2)), uint!(0));
378    /// ```
379    #[must_use]
380    pub fn saturating_sub(self, rhs: Self) -> Self {
381        self.checked_sub(rhs).unwrap_or(Self::MIN)
382    }
383
384    /// Saturating integer multiplication. Computes `self * rhs`, saturating at the numeric
385    /// bounds instead of overflowing.
386    ///
387    /// # Examples
388    ///
389    /// Basic usage:
390    ///
391    /// ```
392    /// # use js_int::{uint, UInt};
393    /// assert_eq!(uint!(100).saturating_mul(uint!(2)), uint!(200));
394    /// assert_eq!(UInt::MAX.saturating_mul(uint!(2)), UInt::MAX);
395    /// assert_eq!(UInt::MAX.saturating_mul(UInt::MAX), UInt::MAX);
396    /// ```
397    #[must_use]
398    pub fn saturating_mul(self, rhs: Self) -> Self {
399        self.checked_mul(rhs).unwrap_or(Self::MAX)
400    }
401
402    /// Saturating integer exponentiation. Computes `self.pow(exp)`, saturating at the
403    /// numeric bounds instead of overflowing or underflowing.
404    ///
405    /// # Examples
406    ///
407    /// Basic usage:
408    ///
409    /// ```
410    /// # use js_int::{uint, UInt};
411    /// assert_eq!(uint!(5).saturating_pow(2), uint!(25));
412    /// assert_eq!(UInt::MAX.saturating_pow(2), UInt::MAX);
413    /// ```
414    #[must_use]
415    pub fn saturating_pow(self, exp: u32) -> Self {
416        Self::new_saturating(self.0.saturating_pow(exp))
417    }
418
419    // TODO: wrapping_* methods, overflowing_* methods
420}
421
422fmt_impls!(UInt);
423convert_impls!(UInt, u8, u16, u32, u64, u128, usize, i8, i16, i32, isize);
424
425impl TryFrom<i8> for UInt {
426    type Error = TryFromIntError;
427
428    fn try_from(val: i8) -> Result<Self, TryFromIntError> {
429        if val >= 0 {
430            Ok(Self(val as u64))
431        } else {
432            Err(TryFromIntError::new())
433        }
434    }
435}
436
437impl TryFrom<i16> for UInt {
438    type Error = TryFromIntError;
439
440    fn try_from(val: i16) -> Result<Self, TryFromIntError> {
441        if val >= 0 {
442            Ok(Self(val as u64))
443        } else {
444            Err(TryFromIntError::new())
445        }
446    }
447}
448
449impl TryFrom<i32> for UInt {
450    type Error = TryFromIntError;
451
452    fn try_from(val: i32) -> Result<Self, TryFromIntError> {
453        if val >= 0 {
454            Ok(Self(val as u64))
455        } else {
456            Err(TryFromIntError::new())
457        }
458    }
459}
460
461impl TryFrom<i64> for UInt {
462    type Error = TryFromIntError;
463
464    fn try_from(val: i64) -> Result<Self, TryFromIntError> {
465        if (0..=MAX_SAFE_INT).contains(&val) {
466            Ok(Self(val as u64))
467        } else {
468            Err(TryFromIntError::new())
469        }
470    }
471}
472
473impl TryFrom<i128> for UInt {
474    type Error = TryFromIntError;
475
476    fn try_from(val: i128) -> Result<Self, TryFromIntError> {
477        if (0..=MAX_SAFE_INT.into()).contains(&val) {
478            Ok(Self(val as u64))
479        } else {
480            Err(TryFromIntError::new())
481        }
482    }
483}
484
485impl From<UInt> for i64 {
486    fn from(val: UInt) -> Self {
487        val.0 as i64
488    }
489}
490
491impl From<UInt> for i128 {
492    fn from(val: UInt) -> Self {
493        val.0 as i128
494    }
495}
496
497macro_rules! uint_op_impl {
498    ($trait:ident, $method:ident, $assign_trait:ident, $assign_method:ident) => {
499        impl $trait for UInt {
500            type Output = Self;
501
502            fn $method(self, rhs: Self) -> Self {
503                Self::new_(<u64 as $trait>::$method(self.0, rhs.0))
504            }
505        }
506
507        impl $assign_trait for UInt {
508            fn $assign_method(&mut self, other: Self) {
509                self.assign_(<u64 as $trait>::$method(self.0, other.0));
510            }
511        }
512    };
513}
514
515uint_op_impl!(Add, add, AddAssign, add_assign);
516uint_op_impl!(Sub, sub, SubAssign, sub_assign);
517uint_op_impl!(Mul, mul, MulAssign, mul_assign);
518uint_op_impl!(Div, div, DivAssign, div_assign);
519uint_op_impl!(Rem, rem, RemAssign, rem_assign);
520
521impl iter::Sum for UInt {
522    fn sum<I>(iter: I) -> Self
523    where
524        I: Iterator<Item = UInt>,
525    {
526        Self::new_(iter.map(|x| x.0).sum())
527    }
528}
529
530impl<'a> iter::Sum<&'a UInt> for UInt {
531    fn sum<I>(iter: I) -> Self
532    where
533        I: Iterator<Item = &'a UInt>,
534    {
535        Self::new_(iter.map(|x| x.0).sum())
536    }
537}
538
539impl iter::Product for UInt {
540    fn product<I>(iter: I) -> Self
541    where
542        I: Iterator<Item = UInt>,
543    {
544        Self::new_(iter.map(|x| x.0).product())
545    }
546}
547
548impl<'a> iter::Product<&'a UInt> for UInt {
549    fn product<I>(iter: I) -> Self
550    where
551        I: Iterator<Item = &'a UInt>,
552    {
553        Self::new_(iter.map(|x| x.0).product())
554    }
555}
556
557impl FromStr for UInt {
558    type Err = ParseIntError;
559
560    fn from_str(src: &str) -> Result<Self, Self::Err> {
561        let val = u64::from_str(src)?;
562        if val > MAX_SAFE_UINT {
563            Err(ParseIntError { kind: ParseIntErrorKind::Overflow })
564        } else {
565            Ok(Self(val))
566        }
567    }
568}
569
570#[cfg(feature = "serde")]
571impl<'de> Deserialize<'de> for UInt {
572    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
573    where
574        D: Deserializer<'de>,
575    {
576        #[cfg(not(feature = "float_deserialize"))]
577        {
578            let val = u64::deserialize(deserializer)?;
579
580            Self::new(val).ok_or_else(|| {
581                D::Error::invalid_value(
582                    Unexpected::Unsigned(val),
583                    &"an integer between 0 and 2^53 - 1",
584                )
585            })
586        }
587
588        #[cfg(feature = "float_deserialize")]
589        {
590            #[cfg(not(feature = "lax_deserialize"))]
591            const EXPECTING: &str = "a number between 0 and 2^53 - 1 without fractional component";
592            #[cfg(feature = "lax_deserialize")]
593            const EXPECTING: &str = "a number between 0 and 2^53 - 1";
594
595            let val = f64::deserialize(deserializer)?;
596
597            if val < 0.0 || val > MAX_SAFE_UINT as f64 || !super::is_acceptable_float(val) {
598                Err(D::Error::invalid_value(Unexpected::Float(val), &EXPECTING))
599            } else {
600                Ok(Self(val as u64))
601            }
602        }
603    }
604}
605
606#[cfg(test)]
607mod tests {
608    use super::{UInt, MAX_SAFE_UINT};
609
610    #[test]
611    fn uint_ops() {
612        assert_eq!(uint!(5) + uint!(3), uint!(8));
613        assert_eq!(uint!(2) - uint!(1), uint!(1));
614        assert_eq!(uint!(4) * uint!(2), uint!(8));
615        assert_eq!(uint!(5) / uint!(2), uint!(2));
616        assert_eq!(uint!(11) % uint!(4), uint!(3));
617    }
618
619    #[test]
620    fn uint_assign_ops() {
621        let mut uint = uint!(1);
622
623        uint += uint!(3);
624        assert_eq!(uint, uint!(4));
625
626        uint -= uint!(1);
627        assert_eq!(uint, uint!(3));
628
629        uint *= uint!(3);
630        assert_eq!(uint, uint!(9));
631
632        uint /= uint!(3);
633        assert_eq!(uint, uint!(3));
634
635        uint %= uint!(2);
636        assert_eq!(uint, uint!(1));
637    }
638
639    #[test]
640    fn uint_wrapping_new() {
641        assert_eq!(UInt::new_wrapping(MAX_SAFE_UINT + 1), uint!(0));
642    }
643
644    #[test]
645    #[cfg_attr(debug_assertions, ignore)]
646    fn uint_underflow_wrap() {
647        assert_eq!(uint!(0) - uint!(1), UInt::MAX);
648    }
649
650    #[test]
651    #[cfg_attr(debug_assertions, ignore)]
652    fn uint_overflow_wrap() {
653        assert_eq!(UInt::MAX + uint!(1), uint!(0));
654        assert_eq!(UInt::MAX + uint!(5), uint!(4));
655    }
656
657    #[test]
658    #[should_panic]
659    #[cfg_attr(not(debug_assertions), ignore)]
660    fn uint_underflow_panic() {
661        let _ = uint!(0) - uint!(1);
662    }
663
664    #[test]
665    #[should_panic]
666    #[cfg_attr(not(debug_assertions), ignore)]
667    fn uint_overflow_panic() {
668        let _ = UInt::MAX + uint!(1);
669    }
670
671    #[test]
672    fn try_from_uint_for_i_n() {
673        use core::convert::TryFrom;
674        let i8_max = i8::MAX as u64;
675        let i16_max = i16::MAX as u64;
676        let i32_max = i32::MAX as u64;
677
678        assert_eq!(i8::try_from(UInt(0)), Ok(0));
679        assert_eq!(i8::try_from(UInt(10)), Ok(10));
680        assert_eq!(i8::try_from(UInt(i8_max)), Ok(i8::MAX));
681        assert!(i8::try_from(UInt(i8_max + 1)).is_err());
682
683        assert_eq!(i16::try_from(UInt(0)), Ok(0));
684        assert_eq!(i16::try_from(UInt(10)), Ok(10));
685        assert_eq!(i16::try_from(UInt(i8_max + 1)), Ok((i8::MAX as i16) + 1));
686        assert_eq!(i16::try_from(UInt(i16_max)), Ok(i16::MAX));
687        assert!(i16::try_from(UInt(i16_max + 1)).is_err());
688
689        assert_eq!(i32::try_from(UInt(0)), Ok(0));
690        assert_eq!(i32::try_from(UInt(10)), Ok(10));
691        assert_eq!(i32::try_from(UInt(i16_max + 1)), Ok((i16::MAX as i32) + 1));
692        assert_eq!(i32::try_from(UInt(i32_max)), Ok(i32::MAX));
693        assert!(i32::try_from(UInt(i32_max + 1)).is_err());
694    }
695}