1use forward_ref::{forward_ref_binop, forward_ref_op_assign};
2use schemars::JsonSchema;
3use serde::{de, ser, Deserialize, Deserializer, Serialize};
4use std::fmt::{self};
5use std::ops::{
6 Add, AddAssign, Div, DivAssign, Mul, MulAssign, Rem, RemAssign, Shr, ShrAssign, Sub, SubAssign,
7};
8
9use crate::errors::{
10 CheckedMultiplyRatioError, DivideByZeroError, OverflowError, OverflowOperation, StdError,
11};
12use crate::Uint128;
13
14#[derive(Copy, Clone, Default, Debug, PartialEq, Eq, PartialOrd, Ord, JsonSchema)]
31pub struct Uint64(#[schemars(with = "String")] u64);
32
33impl Uint64 {
34 pub const MAX: Self = Self(u64::MAX);
35 pub const MIN: Self = Self(u64::MIN);
36
37 pub const fn new(value: u64) -> Self {
41 Uint64(value)
42 }
43
44 #[inline]
46 pub const fn zero() -> Self {
47 Uint64(0)
48 }
49
50 #[inline]
52 pub const fn one() -> Self {
53 Self(1)
54 }
55
56 pub const fn u64(&self) -> u64 {
58 self.0
59 }
60
61 pub const fn to_be_bytes(self) -> [u8; 8] {
63 self.0.to_be_bytes()
64 }
65
66 pub const fn to_le_bytes(self) -> [u8; 8] {
68 self.0.to_le_bytes()
69 }
70
71 pub const fn is_zero(&self) -> bool {
72 self.0 == 0
73 }
74
75 pub fn pow(self, exp: u32) -> Self {
76 self.0.pow(exp).into()
77 }
78
79 pub fn multiply_ratio<A: Into<u64>, B: Into<u64>>(
84 &self,
85 numerator: A,
86 denominator: B,
87 ) -> Uint64 {
88 match self.checked_multiply_ratio(numerator, denominator) {
89 Ok(value) => value,
90 Err(CheckedMultiplyRatioError::DivideByZero) => {
91 panic!("Denominator must not be zero")
92 }
93 Err(CheckedMultiplyRatioError::Overflow) => panic!("Multiplication overflow"),
94 }
95 }
96
97 pub fn checked_multiply_ratio<A: Into<u64>, B: Into<u64>>(
102 &self,
103 numerator: A,
104 denominator: B,
105 ) -> Result<Uint64, CheckedMultiplyRatioError> {
106 let numerator = numerator.into();
107 let denominator = denominator.into();
108 if denominator == 0 {
109 return Err(CheckedMultiplyRatioError::DivideByZero);
110 }
111 match (self.full_mul(numerator) / Uint128::from(denominator)).try_into() {
112 Ok(ratio) => Ok(ratio),
113 Err(_) => Err(CheckedMultiplyRatioError::Overflow),
114 }
115 }
116
117 pub fn full_mul(self, rhs: impl Into<u64>) -> Uint128 {
130 Uint128::from(self.u64())
131 .checked_mul(Uint128::from(rhs.into()))
132 .unwrap()
133 }
134
135 pub fn checked_add(self, other: Self) -> Result<Self, OverflowError> {
136 self.0
137 .checked_add(other.0)
138 .map(Self)
139 .ok_or_else(|| OverflowError::new(OverflowOperation::Add, self, other))
140 }
141
142 pub fn checked_sub(self, other: Self) -> Result<Self, OverflowError> {
143 self.0
144 .checked_sub(other.0)
145 .map(Self)
146 .ok_or_else(|| OverflowError::new(OverflowOperation::Sub, self, other))
147 }
148
149 pub fn checked_mul(self, other: Self) -> Result<Self, OverflowError> {
150 self.0
151 .checked_mul(other.0)
152 .map(Self)
153 .ok_or_else(|| OverflowError::new(OverflowOperation::Mul, self, other))
154 }
155
156 pub fn checked_pow(self, exp: u32) -> Result<Self, OverflowError> {
157 self.0
158 .checked_pow(exp)
159 .map(Self)
160 .ok_or_else(|| OverflowError::new(OverflowOperation::Pow, self, exp))
161 }
162
163 pub fn checked_div(self, other: Self) -> Result<Self, DivideByZeroError> {
164 self.0
165 .checked_div(other.0)
166 .map(Self)
167 .ok_or_else(|| DivideByZeroError::new(self))
168 }
169
170 pub fn checked_div_euclid(self, other: Self) -> Result<Self, DivideByZeroError> {
171 self.0
172 .checked_div_euclid(other.0)
173 .map(Self)
174 .ok_or_else(|| DivideByZeroError::new(self))
175 }
176
177 pub fn checked_rem(self, other: Self) -> Result<Self, DivideByZeroError> {
178 self.0
179 .checked_rem(other.0)
180 .map(Self)
181 .ok_or_else(|| DivideByZeroError::new(self))
182 }
183
184 #[inline]
185 pub fn wrapping_add(self, other: Self) -> Self {
186 Self(self.0.wrapping_add(other.0))
187 }
188
189 #[inline]
190 pub fn wrapping_sub(self, other: Self) -> Self {
191 Self(self.0.wrapping_sub(other.0))
192 }
193
194 #[inline]
195 pub fn wrapping_mul(self, other: Self) -> Self {
196 Self(self.0.wrapping_mul(other.0))
197 }
198
199 #[inline]
200 pub fn wrapping_pow(self, other: u32) -> Self {
201 Self(self.0.wrapping_pow(other))
202 }
203
204 pub fn saturating_add(self, other: Self) -> Self {
205 Self(self.0.saturating_add(other.0))
206 }
207
208 pub fn saturating_sub(self, other: Self) -> Self {
209 Self(self.0.saturating_sub(other.0))
210 }
211
212 pub fn saturating_mul(self, other: Self) -> Self {
213 Self(self.0.saturating_mul(other.0))
214 }
215
216 pub fn saturating_pow(self, exp: u32) -> Self {
217 Self(self.0.saturating_pow(exp))
218 }
219
220 pub const fn abs_diff(self, other: Self) -> Self {
221 Self(if self.0 < other.0 {
222 other.0 - self.0
223 } else {
224 self.0 - other.0
225 })
226 }
227}
228
229impl From<u64> for Uint64 {
235 fn from(val: u64) -> Self {
236 Uint64(val)
237 }
238}
239
240impl From<u32> for Uint64 {
241 fn from(val: u32) -> Self {
242 Uint64(val.into())
243 }
244}
245
246impl From<u16> for Uint64 {
247 fn from(val: u16) -> Self {
248 Uint64(val.into())
249 }
250}
251
252impl From<u8> for Uint64 {
253 fn from(val: u8) -> Self {
254 Uint64(val.into())
255 }
256}
257
258impl TryFrom<&str> for Uint64 {
259 type Error = StdError;
260
261 fn try_from(val: &str) -> Result<Self, Self::Error> {
262 match val.parse::<u64>() {
263 Ok(u) => Ok(Uint64(u)),
264 Err(e) => Err(StdError::generic_err(format!("Parsing u64: {}", e))),
265 }
266 }
267}
268
269impl From<Uint64> for String {
270 fn from(original: Uint64) -> Self {
271 original.to_string()
272 }
273}
274
275impl From<Uint64> for u64 {
276 fn from(original: Uint64) -> Self {
277 original.0
278 }
279}
280
281impl fmt::Display for Uint64 {
282 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
283 self.0.fmt(f)
284 }
285}
286
287impl Add<Uint64> for Uint64 {
288 type Output = Self;
289
290 fn add(self, rhs: Self) -> Self {
291 Uint64(self.u64().checked_add(rhs.u64()).unwrap())
292 }
293}
294
295impl<'a> Add<&'a Uint64> for Uint64 {
296 type Output = Self;
297
298 fn add(self, rhs: &'a Uint64) -> Self {
299 Uint64(self.u64().checked_add(rhs.u64()).unwrap())
300 }
301}
302
303impl Sub<Uint64> for Uint64 {
304 type Output = Self;
305
306 fn sub(self, rhs: Self) -> Self {
307 Uint64(
308 self.u64()
309 .checked_sub(rhs.u64())
310 .expect("attempt to subtract with overflow"),
311 )
312 }
313}
314forward_ref_binop!(impl Sub, sub for Uint64, Uint64);
315
316impl SubAssign<Uint64> for Uint64 {
317 fn sub_assign(&mut self, rhs: Uint64) {
318 *self = *self - rhs;
319 }
320}
321forward_ref_op_assign!(impl SubAssign, sub_assign for Uint64, Uint64);
322
323impl Mul<Uint64> for Uint64 {
324 type Output = Self;
325
326 fn mul(self, rhs: Self) -> Self::Output {
327 Self(
328 self.u64()
329 .checked_mul(rhs.u64())
330 .expect("attempt to multiply with overflow"),
331 )
332 }
333}
334forward_ref_binop!(impl Mul, mul for Uint64, Uint64);
335
336impl MulAssign<Uint64> for Uint64 {
337 fn mul_assign(&mut self, rhs: Self) {
338 *self = *self * rhs;
339 }
340}
341forward_ref_op_assign!(impl MulAssign, mul_assign for Uint64, Uint64);
342
343impl Div<Uint64> for Uint64 {
344 type Output = Self;
345
346 fn div(self, rhs: Self) -> Self::Output {
347 Self(self.u64().checked_div(rhs.u64()).unwrap())
348 }
349}
350
351impl<'a> Div<&'a Uint64> for Uint64 {
352 type Output = Self;
353
354 fn div(self, rhs: &'a Uint64) -> Self::Output {
355 Self(self.u64().checked_div(rhs.u64()).unwrap())
356 }
357}
358
359impl Rem for Uint64 {
360 type Output = Self;
361
362 #[inline]
366 fn rem(self, rhs: Self) -> Self {
367 Self(self.0.rem(rhs.0))
368 }
369}
370forward_ref_binop!(impl Rem, rem for Uint64, Uint64);
371
372impl RemAssign<Uint64> for Uint64 {
373 fn rem_assign(&mut self, rhs: Uint64) {
374 *self = *self % rhs;
375 }
376}
377forward_ref_op_assign!(impl RemAssign, rem_assign for Uint64, Uint64);
378
379impl Shr<u32> for Uint64 {
380 type Output = Self;
381
382 fn shr(self, rhs: u32) -> Self::Output {
383 Self(self.u64().checked_shr(rhs).unwrap())
384 }
385}
386
387impl<'a> Shr<&'a u32> for Uint64 {
388 type Output = Self;
389
390 fn shr(self, rhs: &'a u32) -> Self::Output {
391 Self(self.u64().checked_shr(*rhs).unwrap())
392 }
393}
394
395impl AddAssign<Uint64> for Uint64 {
396 fn add_assign(&mut self, rhs: Uint64) {
397 self.0 = self.0.checked_add(rhs.u64()).unwrap();
398 }
399}
400
401impl<'a> AddAssign<&'a Uint64> for Uint64 {
402 fn add_assign(&mut self, rhs: &'a Uint64) {
403 self.0 = self.0.checked_add(rhs.u64()).unwrap();
404 }
405}
406
407impl DivAssign<Uint64> for Uint64 {
408 fn div_assign(&mut self, rhs: Self) {
409 self.0 = self.0.checked_div(rhs.u64()).unwrap();
410 }
411}
412
413impl<'a> DivAssign<&'a Uint64> for Uint64 {
414 fn div_assign(&mut self, rhs: &'a Uint64) {
415 self.0 = self.0.checked_div(rhs.u64()).unwrap();
416 }
417}
418
419impl ShrAssign<u32> for Uint64 {
420 fn shr_assign(&mut self, rhs: u32) {
421 self.0 = self.0.checked_shr(rhs).unwrap();
422 }
423}
424
425impl<'a> ShrAssign<&'a u32> for Uint64 {
426 fn shr_assign(&mut self, rhs: &'a u32) {
427 self.0 = self.0.checked_shr(*rhs).unwrap();
428 }
429}
430
431impl Serialize for Uint64 {
432 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
434 where
435 S: ser::Serializer,
436 {
437 serializer.serialize_str(&self.to_string())
438 }
439}
440
441impl<'de> Deserialize<'de> for Uint64 {
442 fn deserialize<D>(deserializer: D) -> Result<Uint64, D::Error>
444 where
445 D: Deserializer<'de>,
446 {
447 deserializer.deserialize_str(Uint64Visitor)
448 }
449}
450
451struct Uint64Visitor;
452
453impl<'de> de::Visitor<'de> for Uint64Visitor {
454 type Value = Uint64;
455
456 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
457 formatter.write_str("string-encoded integer")
458 }
459
460 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
461 where
462 E: de::Error,
463 {
464 match v.parse::<u64>() {
465 Ok(u) => Ok(Uint64(u)),
466 Err(e) => Err(E::custom(format!("invalid Uint64 '{}' - {}", v, e))),
467 }
468 }
469}
470
471impl<A> std::iter::Sum<A> for Uint64
472where
473 Self: Add<A, Output = Self>,
474{
475 fn sum<I: Iterator<Item = A>>(iter: I) -> Self {
476 iter.fold(Self::zero(), Add::add)
477 }
478}
479
480impl PartialEq<&Uint64> for Uint64 {
481 fn eq(&self, rhs: &&Uint64) -> bool {
482 self == *rhs
483 }
484}
485
486impl PartialEq<Uint64> for &Uint64 {
487 fn eq(&self, rhs: &Uint64) -> bool {
488 *self == rhs
489 }
490}
491
492#[cfg(test)]
493mod tests {
494 use super::*;
495 use crate::{from_slice, to_vec};
496
497 #[test]
498 fn uint64_zero_works() {
499 let zero = Uint64::zero();
500 assert_eq!(zero.to_be_bytes(), [0, 0, 0, 0, 0, 0, 0, 0]);
501 }
502
503 #[test]
504 fn uint64_one_works() {
505 let one = Uint64::one();
506 assert_eq!(one.to_be_bytes(), [0, 0, 0, 0, 0, 0, 0, 1]);
507 }
508
509 #[test]
510 fn uint64_convert_into() {
511 let original = Uint64(12345);
512 let a = u64::from(original);
513 assert_eq!(a, 12345);
514
515 let original = Uint64(12345);
516 let a = String::from(original);
517 assert_eq!(a, "12345");
518 }
519
520 #[test]
521 fn uint64_convert_from() {
522 let a = Uint64::from(5u64);
523 assert_eq!(a.0, 5);
524
525 let a = Uint64::from(5u32);
526 assert_eq!(a.0, 5);
527
528 let a = Uint64::from(5u16);
529 assert_eq!(a.0, 5);
530
531 let a = Uint64::from(5u8);
532 assert_eq!(a.0, 5);
533
534 let result = Uint64::try_from("34567");
535 assert_eq!(result.unwrap().0, 34567);
536
537 let result = Uint64::try_from("1.23");
538 assert!(result.is_err());
539 }
540
541 #[test]
542 fn uint64_implements_display() {
543 let a = Uint64(12345);
544 assert_eq!(format!("Embedded: {}", a), "Embedded: 12345");
545 assert_eq!(a.to_string(), "12345");
546
547 let a = Uint64(0);
548 assert_eq!(format!("Embedded: {}", a), "Embedded: 0");
549 assert_eq!(a.to_string(), "0");
550 }
551
552 #[test]
553 fn uint64_display_padding_works() {
554 let a = Uint64::from(123u64);
555 assert_eq!(format!("Embedded: {:05}", a), "Embedded: 00123");
556 }
557
558 #[test]
559 fn uint64_to_be_bytes_works() {
560 assert_eq!(Uint64::zero().to_be_bytes(), [0, 0, 0, 0, 0, 0, 0, 0]);
561 assert_eq!(
562 Uint64::MAX.to_be_bytes(),
563 [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]
564 );
565 assert_eq!(Uint64::new(1).to_be_bytes(), [0, 0, 0, 0, 0, 0, 0, 1]);
566 assert_eq!(
568 Uint64::new(874607431768124608).to_be_bytes(),
569 [12, 35, 58, 211, 72, 116, 172, 192]
570 );
571 }
572
573 #[test]
574 fn uint64_to_le_bytes_works() {
575 assert_eq!(Uint64::zero().to_le_bytes(), [0, 0, 0, 0, 0, 0, 0, 0]);
576 assert_eq!(
577 Uint64::MAX.to_le_bytes(),
578 [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]
579 );
580 assert_eq!(Uint64::new(1).to_le_bytes(), [1, 0, 0, 0, 0, 0, 0, 0]);
581 assert_eq!(
583 Uint64::new(874607431768124608).to_le_bytes(),
584 [192, 172, 116, 72, 211, 58, 35, 12]
585 );
586 }
587
588 #[test]
589 fn uint64_is_zero_works() {
590 assert!(Uint64::zero().is_zero());
591 assert!(Uint64(0).is_zero());
592
593 assert!(!Uint64(1).is_zero());
594 assert!(!Uint64(123).is_zero());
595 }
596
597 #[test]
598 fn uint64_json() {
599 let orig = Uint64(1234567890987654321);
600 let serialized = to_vec(&orig).unwrap();
601 assert_eq!(serialized.as_slice(), b"\"1234567890987654321\"");
602 let parsed: Uint64 = from_slice(&serialized).unwrap();
603 assert_eq!(parsed, orig);
604 }
605
606 #[test]
607 fn uint64_compare() {
608 let a = Uint64(12345);
609 let b = Uint64(23456);
610
611 assert!(a < b);
612 assert!(b > a);
613 assert_eq!(a, Uint64(12345));
614 }
615
616 #[test]
617 #[allow(clippy::op_ref)]
618 fn uint64_math() {
619 let a = Uint64(12345);
620 let b = Uint64(23456);
621
622 assert_eq!(a + b, Uint64(35801));
624 assert_eq!(a + &b, Uint64(35801));
625
626 assert_eq!((b.checked_sub(a)).unwrap(), Uint64(11111));
628
629 let mut c = Uint64(300000);
631 c += b;
632 assert_eq!(c, Uint64(323456));
633 let mut d = Uint64(300000);
634 d += &b;
635 assert_eq!(d, Uint64(323456));
636
637 let underflow_result = a.checked_sub(b);
639 let OverflowError {
640 operand1, operand2, ..
641 } = underflow_result.unwrap_err();
642 assert_eq!((operand1, operand2), (a.to_string(), b.to_string()));
643 }
644
645 #[test]
646 #[allow(clippy::op_ref)]
647 fn uint64_sub_works() {
648 assert_eq!(Uint64(2) - Uint64(1), Uint64(1));
649 assert_eq!(Uint64(2) - Uint64(0), Uint64(2));
650 assert_eq!(Uint64(2) - Uint64(2), Uint64(0));
651
652 let a = Uint64::new(10);
654 let b = Uint64::new(3);
655 let expected = Uint64::new(7);
656 assert_eq!(a - b, expected);
657 assert_eq!(a - &b, expected);
658 assert_eq!(&a - b, expected);
659 assert_eq!(&a - &b, expected);
660 }
661
662 #[test]
663 #[should_panic]
664 fn uint64_sub_overflow_panics() {
665 let _ = Uint64(1) - Uint64(2);
666 }
667
668 #[test]
669 fn uint64_sub_assign_works() {
670 let mut a = Uint64(14);
671 a -= Uint64(2);
672 assert_eq!(a, Uint64(12));
673
674 let mut a = Uint64::new(10);
676 let b = Uint64::new(3);
677 let expected = Uint64::new(7);
678 a -= &b;
679 assert_eq!(a, expected);
680 }
681
682 #[test]
683 #[allow(clippy::op_ref)]
684 fn uint64_mul_works() {
685 assert_eq!(Uint64::from(2u32) * Uint64::from(3u32), Uint64::from(6u32));
686 assert_eq!(Uint64::from(2u32) * Uint64::zero(), Uint64::zero());
687
688 let a = Uint64::from(11u32);
690 let b = Uint64::from(3u32);
691 let expected = Uint64::from(33u32);
692 assert_eq!(a * b, expected);
693 assert_eq!(a * &b, expected);
694 assert_eq!(&a * b, expected);
695 assert_eq!(&a * &b, expected);
696 }
697
698 #[test]
699 fn uint64_mul_assign_works() {
700 let mut a = Uint64::from(14u32);
701 a *= Uint64::from(2u32);
702 assert_eq!(a, Uint64::from(28u32));
703
704 let mut a = Uint64::from(10u32);
706 let b = Uint64::from(3u32);
707 a *= &b;
708 assert_eq!(a, Uint64::from(30u32));
709 }
710
711 #[test]
712 fn uint64_pow_works() {
713 assert_eq!(Uint64::from(2u32).pow(2), Uint64::from(4u32));
714 assert_eq!(Uint64::from(2u32).pow(10), Uint64::from(1024u32));
715 }
716
717 #[test]
718 #[should_panic]
719 fn uint64_pow_overflow_panics() {
720 Uint64::MAX.pow(2u32);
721 }
722
723 #[test]
724 #[should_panic]
725 fn uint64_math_overflow_panics() {
726 let almost_max = Uint64(18446744073709551606);
728 let _ = almost_max + Uint64(12);
729 }
730
731 #[test]
732 fn uint64_multiply_ratio_works() {
733 let base = Uint64(500);
734
735 assert_eq!(base.multiply_ratio(1u64, 1u64), base);
737 assert_eq!(base.multiply_ratio(3u64, 3u64), base);
738 assert_eq!(base.multiply_ratio(654321u64, 654321u64), base);
739 assert_eq!(base.multiply_ratio(u64::MAX, u64::MAX), base);
740
741 assert_eq!(base.multiply_ratio(3u64, 2u64), Uint64(750));
743 assert_eq!(base.multiply_ratio(333333u64, 222222u64), Uint64(750));
744
745 assert_eq!(base.multiply_ratio(2u64, 3u64), Uint64(333));
747 assert_eq!(base.multiply_ratio(222222u64, 333333u64), Uint64(333));
748
749 assert_eq!(base.multiply_ratio(5u64, 6u64), Uint64(416));
751 assert_eq!(base.multiply_ratio(100u64, 120u64), Uint64(416));
752 }
753
754 #[test]
755 fn uint64_multiply_ratio_does_not_overflow_when_result_fits() {
756 let base = Uint64(u64::MAX - 9);
758
759 assert_eq!(base.multiply_ratio(2u64, 2u64), base);
760 }
761
762 #[test]
763 #[should_panic]
764 fn uint64_multiply_ratio_panicks_on_overflow() {
765 let base = Uint64(u64::MAX - 9);
767
768 assert_eq!(base.multiply_ratio(2u64, 1u64), base);
769 }
770
771 #[test]
772 #[should_panic(expected = "Denominator must not be zero")]
773 fn uint64_multiply_ratio_panics_for_zero_denominator() {
774 Uint64(500).multiply_ratio(1u64, 0u64);
775 }
776
777 #[test]
778 fn uint64_checked_multiply_ratio_does_not_panic() {
779 assert_eq!(
780 Uint64(500u64).checked_multiply_ratio(1u64, 0u64),
781 Err(CheckedMultiplyRatioError::DivideByZero),
782 );
783 assert_eq!(
784 Uint64(500u64).checked_multiply_ratio(u64::MAX, 1u64),
785 Err(CheckedMultiplyRatioError::Overflow),
786 );
787 }
788
789 #[test]
790 fn sum_works() {
791 let nums = vec![Uint64(17), Uint64(123), Uint64(540), Uint64(82)];
792 let expected = Uint64(762);
793
794 let sum_as_ref: Uint64 = nums.iter().sum();
795 assert_eq!(expected, sum_as_ref);
796
797 let sum_as_owned: Uint64 = nums.into_iter().sum();
798 assert_eq!(expected, sum_as_owned);
799 }
800
801 #[test]
802 fn uint64_methods() {
803 assert!(matches!(
805 Uint64::MAX.checked_add(Uint64(1)),
806 Err(OverflowError { .. })
807 ));
808 assert!(matches!(Uint64(1).checked_add(Uint64(1)), Ok(Uint64(2))));
809 assert!(matches!(
810 Uint64(0).checked_sub(Uint64(1)),
811 Err(OverflowError { .. })
812 ));
813 assert!(matches!(Uint64(2).checked_sub(Uint64(1)), Ok(Uint64(1))));
814 assert!(matches!(
815 Uint64::MAX.checked_mul(Uint64(2)),
816 Err(OverflowError { .. })
817 ));
818 assert!(matches!(Uint64(2).checked_mul(Uint64(2)), Ok(Uint64(4))));
819 assert!(matches!(
820 Uint64::MAX.checked_pow(2u32),
821 Err(OverflowError { .. })
822 ));
823 assert!(matches!(Uint64(2).checked_pow(3), Ok(Uint64(8))));
824 assert!(matches!(
825 Uint64::MAX.checked_div(Uint64(0)),
826 Err(DivideByZeroError { .. })
827 ));
828 assert!(matches!(Uint64(6).checked_div(Uint64(2)), Ok(Uint64(3))));
829 assert!(matches!(
830 Uint64::MAX.checked_div_euclid(Uint64(0)),
831 Err(DivideByZeroError { .. })
832 ));
833 assert!(matches!(
834 Uint64(6).checked_div_euclid(Uint64(2)),
835 Ok(Uint64(3)),
836 ));
837 assert!(matches!(
838 Uint64::MAX.checked_rem(Uint64(0)),
839 Err(DivideByZeroError { .. })
840 ));
841 assert!(matches!(Uint64(7).checked_rem(Uint64(2)), Ok(Uint64(1))));
842
843 assert_eq!(Uint64::MAX.saturating_add(Uint64(1)), Uint64::MAX);
845 assert_eq!(Uint64(0).saturating_sub(Uint64(1)), Uint64(0));
846 assert_eq!(Uint64::MAX.saturating_mul(Uint64(2)), Uint64::MAX);
847 assert_eq!(Uint64::MAX.saturating_pow(2), Uint64::MAX);
848 }
849
850 #[test]
851 fn uint64_wrapping_methods() {
852 assert_eq!(Uint64(2).wrapping_add(Uint64(2)), Uint64(4)); assert_eq!(Uint64::MAX.wrapping_add(Uint64(1)), Uint64(0)); assert_eq!(Uint64(7).wrapping_sub(Uint64(5)), Uint64(2)); assert_eq!(Uint64(0).wrapping_sub(Uint64(1)), Uint64::MAX); assert_eq!(Uint64(3).wrapping_mul(Uint64(2)), Uint64(6)); assert_eq!(
863 Uint64::MAX.wrapping_mul(Uint64(2)),
864 Uint64::MAX - Uint64::one()
865 ); assert_eq!(Uint64(2).wrapping_pow(3), Uint64(8)); assert_eq!(Uint64::MAX.wrapping_pow(2), Uint64(1)); }
871
872 #[test]
873 #[allow(clippy::op_ref)]
874 fn uint64_implements_rem() {
875 let a = Uint64::new(10);
876 assert_eq!(a % Uint64::new(10), Uint64::zero());
877 assert_eq!(a % Uint64::new(2), Uint64::zero());
878 assert_eq!(a % Uint64::new(1), Uint64::zero());
879 assert_eq!(a % Uint64::new(3), Uint64::new(1));
880 assert_eq!(a % Uint64::new(4), Uint64::new(2));
881
882 let a = Uint64::new(10);
884 let b = Uint64::new(3);
885 let expected = Uint64::new(1);
886 assert_eq!(a % b, expected);
887 assert_eq!(a % &b, expected);
888 assert_eq!(&a % b, expected);
889 assert_eq!(&a % &b, expected);
890 }
891
892 #[test]
893 #[should_panic(expected = "divisor of zero")]
894 fn uint64_rem_panics_for_zero() {
895 let _ = Uint64::new(10) % Uint64::zero();
896 }
897
898 #[test]
899 #[allow(clippy::op_ref)]
900 fn uint64_rem_works() {
901 assert_eq!(
902 Uint64::from(12u32) % Uint64::from(10u32),
903 Uint64::from(2u32)
904 );
905 assert_eq!(Uint64::from(50u32) % Uint64::from(5u32), Uint64::zero());
906
907 let a = Uint64::from(42u32);
909 let b = Uint64::from(5u32);
910 let expected = Uint64::from(2u32);
911 assert_eq!(a % b, expected);
912 assert_eq!(a % &b, expected);
913 assert_eq!(&a % b, expected);
914 assert_eq!(&a % &b, expected);
915 }
916
917 #[test]
918 fn uint64_rem_assign_works() {
919 let mut a = Uint64::from(30u32);
920 a %= Uint64::from(4u32);
921 assert_eq!(a, Uint64::from(2u32));
922
923 let mut a = Uint64::from(25u32);
925 let b = Uint64::from(6u32);
926 a %= &b;
927 assert_eq!(a, Uint64::from(1u32));
928 }
929
930 #[test]
931 fn uint64_abs_diff_works() {
932 let a = Uint64::from(42u32);
933 let b = Uint64::from(5u32);
934 let expected = Uint64::from(37u32);
935 assert_eq!(a.abs_diff(b), expected);
936 assert_eq!(b.abs_diff(a), expected);
937 }
938
939 #[test]
940 fn uint64_partial_eq() {
941 let test_cases = [(1, 1, true), (42, 42, true), (42, 24, false), (0, 0, true)]
942 .into_iter()
943 .map(|(lhs, rhs, expected)| (Uint64::new(lhs), Uint64::new(rhs), expected));
944
945 #[allow(clippy::op_ref)]
946 for (lhs, rhs, expected) in test_cases {
947 assert_eq!(lhs == rhs, expected);
948 assert_eq!(&lhs == rhs, expected);
949 assert_eq!(lhs == &rhs, expected);
950 assert_eq!(&lhs == &rhs, expected);
951 }
952 }
953}