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}