1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
// suppress `use_self` recommendation; not avoidable in macro context
#![allow(clippy::use_self)]

#[cfg(test)]
mod unit_tests;

pub trait ICheckedOps<T = Self>: Sized
where
    Self: PartialOrd,
{
    type Output;

    fn checked_abs(self) -> Self::Output;
    fn checked_add(self, rhs: T) -> Self::Output;
    fn checked_div(self, rhs: T) -> Self::Output;
    fn checked_div_euclid(self, rhs: T) -> Self::Output;
    fn checked_mul(self, rhs: T) -> Self::Output;
    fn checked_neg(self) -> Self::Output;
    fn checked_pow(self, rhs: u32) -> Self::Output;
    fn checked_rem(self, rhs: T) -> Self::Output;
    fn checked_rem_euclid(self, rhs: T) -> Self::Output;
    fn checked_shl(self, rhs: u32) -> Self::Output;
    fn checked_shr(self, rhs: u32) -> Self::Output;
    fn checked_sub(self, rhs: T) -> Self::Output;
}

macro_rules! checked_impl {
    ($tr:ty; $($t:ty),+ $(,)?) => ($(
        impl ICheckedOps for $t {
            type Output = Option<Self>;

            binary_op_impl! {
                $tr, $t;
                checked_add,
                checked_div,
                checked_div_euclid,
                checked_mul,
                checked_rem,
                checked_rem_euclid,
                checked_sub
            }

            binary_op_impl! {
                $tr, u32;
                checked_pow,
                checked_shl,
                checked_shr
            }

            unary_op_impl! {
                checked_abs,
                checked_neg
            }
        }
    )*)
}

checked_impl! { ICheckedOps; i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize, }