1 use std::ops::{Add, Sub, Mul, Div};
2 
3 /// Performs addition that returns `None` instead of wrapping around on
4 /// overflow.
5 pub trait CheckedAdd: Sized + Add<Self, Output=Self> {
6     /// Adds two numbers, checking for overflow. If overflow happens, `None` is
7     /// returned.
checked_add(&self, v: &Self) -> Option<Self>8     fn checked_add(&self, v: &Self) -> Option<Self>;
9 }
10 
11 macro_rules! checked_impl {
12     ($trait_name:ident, $method:ident, $t:ty) => {
13         impl $trait_name for $t {
14             #[inline]
15             fn $method(&self, v: &$t) -> Option<$t> {
16                 <$t>::$method(*self, *v)
17             }
18         }
19     }
20 }
21 
22 checked_impl!(CheckedAdd, checked_add, u8);
23 checked_impl!(CheckedAdd, checked_add, u16);
24 checked_impl!(CheckedAdd, checked_add, u32);
25 checked_impl!(CheckedAdd, checked_add, u64);
26 checked_impl!(CheckedAdd, checked_add, usize);
27 
28 checked_impl!(CheckedAdd, checked_add, i8);
29 checked_impl!(CheckedAdd, checked_add, i16);
30 checked_impl!(CheckedAdd, checked_add, i32);
31 checked_impl!(CheckedAdd, checked_add, i64);
32 checked_impl!(CheckedAdd, checked_add, isize);
33 
34 /// Performs subtraction that returns `None` instead of wrapping around on underflow.
35 pub trait CheckedSub: Sized + Sub<Self, Output=Self> {
36     /// Subtracts two numbers, checking for underflow. If underflow happens,
37     /// `None` is returned.
checked_sub(&self, v: &Self) -> Option<Self>38     fn checked_sub(&self, v: &Self) -> Option<Self>;
39 }
40 
41 checked_impl!(CheckedSub, checked_sub, u8);
42 checked_impl!(CheckedSub, checked_sub, u16);
43 checked_impl!(CheckedSub, checked_sub, u32);
44 checked_impl!(CheckedSub, checked_sub, u64);
45 checked_impl!(CheckedSub, checked_sub, usize);
46 
47 checked_impl!(CheckedSub, checked_sub, i8);
48 checked_impl!(CheckedSub, checked_sub, i16);
49 checked_impl!(CheckedSub, checked_sub, i32);
50 checked_impl!(CheckedSub, checked_sub, i64);
51 checked_impl!(CheckedSub, checked_sub, isize);
52 
53 /// Performs multiplication that returns `None` instead of wrapping around on underflow or
54 /// overflow.
55 pub trait CheckedMul: Sized + Mul<Self, Output=Self> {
56     /// Multiplies two numbers, checking for underflow or overflow. If underflow
57     /// or overflow happens, `None` is returned.
checked_mul(&self, v: &Self) -> Option<Self>58     fn checked_mul(&self, v: &Self) -> Option<Self>;
59 }
60 
61 checked_impl!(CheckedMul, checked_mul, u8);
62 checked_impl!(CheckedMul, checked_mul, u16);
63 checked_impl!(CheckedMul, checked_mul, u32);
64 checked_impl!(CheckedMul, checked_mul, u64);
65 checked_impl!(CheckedMul, checked_mul, usize);
66 
67 checked_impl!(CheckedMul, checked_mul, i8);
68 checked_impl!(CheckedMul, checked_mul, i16);
69 checked_impl!(CheckedMul, checked_mul, i32);
70 checked_impl!(CheckedMul, checked_mul, i64);
71 checked_impl!(CheckedMul, checked_mul, isize);
72 
73 /// Performs division that returns `None` instead of panicking on division by zero and instead of
74 /// wrapping around on underflow and overflow.
75 pub trait CheckedDiv: Sized + Div<Self, Output=Self> {
76     /// Divides two numbers, checking for underflow, overflow and division by
77     /// zero. If any of that happens, `None` is returned.
checked_div(&self, v: &Self) -> Option<Self>78     fn checked_div(&self, v: &Self) -> Option<Self>;
79 }
80 
81 checked_impl!(CheckedDiv, checked_div, u8);
82 checked_impl!(CheckedDiv, checked_div, u16);
83 checked_impl!(CheckedDiv, checked_div, u32);
84 checked_impl!(CheckedDiv, checked_div, u64);
85 checked_impl!(CheckedDiv, checked_div, usize);
86 
87 checked_impl!(CheckedDiv, checked_div, i8);
88 checked_impl!(CheckedDiv, checked_div, i16);
89 checked_impl!(CheckedDiv, checked_div, i32);
90 checked_impl!(CheckedDiv, checked_div, i64);
91 checked_impl!(CheckedDiv, checked_div, isize);
92 
93