nam_num_traits/ops/
overflowing.rs

1use core::{i128, i16, i32, i64, i8, isize};
2use core::{u128, u16, u32, u64, u8, usize};
3
4macro_rules! overflowing_impl {
5    ($trait_name:ident, $method:ident, $t:ty) => {
6        impl $trait_name<$t> for $t {
7            type Output = $t;
8            #[inline]
9            fn $method(self, v: $t) -> ($t, bool) {
10                <$t>::$method(self, v)
11            }
12        }
13
14        impl $trait_name<&$t> for $t {
15            type Output = $t;
16            #[inline]
17            fn $method(self, v: &$t) -> ($t, bool) {
18                <$t>::$method(self, *v)
19            }
20        }
21
22        impl $trait_name<$t> for &$t {
23            type Output = $t;
24            #[inline]
25            fn $method(self, v: $t) -> ($t, bool) {
26                <$t>::$method(*self, v)
27            }
28        }
29
30        impl $trait_name<&$t> for &$t {
31            type Output = $t;
32            #[inline]
33            fn $method(self, v: &$t) -> ($t, bool) {
34                <$t>::$method(*self, *v)
35            }
36        }
37    };
38}
39
40/// Performs addition with a flag for overflow.
41pub trait OverflowingAdd<Rhs = Self>: Sized {
42    type Output;
43    /// Returns a tuple of the sum along with a boolean indicating whether an arithmetic overflow would occur.
44    /// If an overflow would have occurred then the wrapped value is returned.
45    fn overflowing_add(self, v: Rhs) -> (Self::Output, bool);
46}
47
48overflowing_impl!(OverflowingAdd, overflowing_add, u8);
49overflowing_impl!(OverflowingAdd, overflowing_add, u16);
50overflowing_impl!(OverflowingAdd, overflowing_add, u32);
51overflowing_impl!(OverflowingAdd, overflowing_add, u64);
52overflowing_impl!(OverflowingAdd, overflowing_add, usize);
53overflowing_impl!(OverflowingAdd, overflowing_add, u128);
54
55overflowing_impl!(OverflowingAdd, overflowing_add, i8);
56overflowing_impl!(OverflowingAdd, overflowing_add, i16);
57overflowing_impl!(OverflowingAdd, overflowing_add, i32);
58overflowing_impl!(OverflowingAdd, overflowing_add, i64);
59overflowing_impl!(OverflowingAdd, overflowing_add, isize);
60overflowing_impl!(OverflowingAdd, overflowing_add, i128);
61
62/// Performs substraction with a flag for overflow.
63pub trait OverflowingSub<Rhs = Self>: Sized {
64    type Output;
65    /// Returns a tuple of the difference along with a boolean indicating whether an arithmetic overflow would occur.
66    /// If an overflow would have occurred then the wrapped value is returned.
67    fn overflowing_sub(self, v: Rhs) -> (Self::Output, bool);
68}
69
70overflowing_impl!(OverflowingSub, overflowing_sub, u8);
71overflowing_impl!(OverflowingSub, overflowing_sub, u16);
72overflowing_impl!(OverflowingSub, overflowing_sub, u32);
73overflowing_impl!(OverflowingSub, overflowing_sub, u64);
74overflowing_impl!(OverflowingSub, overflowing_sub, usize);
75overflowing_impl!(OverflowingSub, overflowing_sub, u128);
76
77overflowing_impl!(OverflowingSub, overflowing_sub, i8);
78overflowing_impl!(OverflowingSub, overflowing_sub, i16);
79overflowing_impl!(OverflowingSub, overflowing_sub, i32);
80overflowing_impl!(OverflowingSub, overflowing_sub, i64);
81overflowing_impl!(OverflowingSub, overflowing_sub, isize);
82overflowing_impl!(OverflowingSub, overflowing_sub, i128);
83
84/// Performs multiplication with a flag for overflow.
85pub trait OverflowingMul<Rhs = Self>: Sized {
86    type Output;
87    /// Returns a tuple of the product along with a boolean indicating whether an arithmetic overflow would occur.
88    /// If an overflow would have occurred then the wrapped value is returned.
89    fn overflowing_mul(self, v: Rhs) -> (Self::Output, bool);
90}
91
92overflowing_impl!(OverflowingMul, overflowing_mul, u8);
93overflowing_impl!(OverflowingMul, overflowing_mul, u16);
94overflowing_impl!(OverflowingMul, overflowing_mul, u32);
95overflowing_impl!(OverflowingMul, overflowing_mul, u64);
96overflowing_impl!(OverflowingMul, overflowing_mul, usize);
97overflowing_impl!(OverflowingMul, overflowing_mul, u128);
98
99overflowing_impl!(OverflowingMul, overflowing_mul, i8);
100overflowing_impl!(OverflowingMul, overflowing_mul, i16);
101overflowing_impl!(OverflowingMul, overflowing_mul, i32);
102overflowing_impl!(OverflowingMul, overflowing_mul, i64);
103overflowing_impl!(OverflowingMul, overflowing_mul, isize);
104overflowing_impl!(OverflowingMul, overflowing_mul, i128);
105
106#[test]
107fn test_overflowing_traits() {
108    fn overflowing_add<T: OverflowingAdd>(a: T, b: T) -> (T, bool) {
109        a.overflowing_add(&b)
110    }
111    fn overflowing_sub<T: OverflowingSub>(a: T, b: T) -> (T, bool) {
112        a.overflowing_sub(&b)
113    }
114    fn overflowing_mul<T: OverflowingMul>(a: T, b: T) -> (T, bool) {
115        a.overflowing_mul(&b)
116    }
117    assert_eq!(overflowing_add(5i16, 2), (7, false));
118    assert_eq!(overflowing_add(i16::MAX, 1), (i16::MIN, true));
119    assert_eq!(overflowing_sub(5i16, 2), (3, false));
120    assert_eq!(overflowing_sub(i16::MIN, 1), (i16::MAX, true));
121    assert_eq!(overflowing_mul(5i16, 2), (10, false));
122    assert_eq!(overflowing_mul(1_000_000_000i32, 10), (1410065408, true));
123}