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