Skip to main content

use_arithmetic/
wrapping.rs

1#![allow(clippy::module_name_repetitions)]
2
3mod sealed {
4    pub trait Sealed {}
5
6    macro_rules! impl_sealed {
7        ($($ty:ty),* $(,)?) => {
8            $(impl Sealed for $ty {})*
9        };
10    }
11
12    impl_sealed!(
13        u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize
14    );
15}
16
17/// Primitive integer types supported by the wrapping arithmetic wrappers.
18pub trait WrappingArithmetic: sealed::Sealed + Sized {
19    /// Returns the wrapping sum of `self` and `rhs`.
20    #[must_use]
21    fn wrapping_add(self, rhs: Self) -> Self;
22
23    /// Returns the wrapping difference of `self` and `rhs`.
24    #[must_use]
25    fn wrapping_sub(self, rhs: Self) -> Self;
26
27    /// Returns the wrapping product of `self` and `rhs`.
28    #[must_use]
29    fn wrapping_mul(self, rhs: Self) -> Self;
30}
31
32macro_rules! impl_wrapping_arithmetic {
33    ($($ty:ty),* $(,)?) => {
34        $(impl WrappingArithmetic for $ty {
35            fn wrapping_add(self, rhs: Self) -> Self {
36                <$ty>::wrapping_add(self, rhs)
37            }
38
39            fn wrapping_sub(self, rhs: Self) -> Self {
40                <$ty>::wrapping_sub(self, rhs)
41            }
42
43            fn wrapping_mul(self, rhs: Self) -> Self {
44                <$ty>::wrapping_mul(self, rhs)
45            }
46        })*
47    };
48}
49
50impl_wrapping_arithmetic!(
51    u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize
52);
53
54/// Returns the wrapping sum of `left` and `right`.
55#[must_use]
56pub fn wrapping_add<T: WrappingArithmetic>(left: T, right: T) -> T {
57    <T as WrappingArithmetic>::wrapping_add(left, right)
58}
59
60/// Returns the wrapping difference of `left` and `right`.
61#[must_use]
62pub fn wrapping_sub<T: WrappingArithmetic>(left: T, right: T) -> T {
63    <T as WrappingArithmetic>::wrapping_sub(left, right)
64}
65
66/// Returns the wrapping product of `left` and `right`.
67#[must_use]
68pub fn wrapping_mul<T: WrappingArithmetic>(left: T, right: T) -> T {
69    <T as WrappingArithmetic>::wrapping_mul(left, right)
70}
71
72#[cfg(test)]
73mod tests {
74    use super::{wrapping_add, wrapping_mul, wrapping_sub};
75
76    #[test]
77    fn wraps_unsigned_values() {
78        assert_eq!(wrapping_add(u8::MAX, 1), 0);
79        assert_eq!(wrapping_sub(0_u8, 1), u8::MAX);
80        assert_eq!(wrapping_mul(200_u8, 2), 144);
81    }
82
83    #[test]
84    fn wraps_signed_values() {
85        assert_eq!(wrapping_add(i8::MAX, 1), i8::MIN);
86        assert_eq!(wrapping_sub(i8::MIN, 1), i8::MAX);
87        assert_eq!(wrapping_mul(100_i8, 2), -56);
88    }
89}