option_operations/
add.rs

1//! Traits for the addition [`OptionOperations`].
2
3use core::ops::{Add, AddAssign};
4
5use crate::{Error, OptionOperations};
6
7common_option_op!(Add, add, addition);
8
9impl_for_ints!(OptionOverflowingAdd, {
10    type Output = Self;
11    fn opt_overflowing_add(self, rhs: Self) -> Option<(Self::Output, bool)> {
12        Some(self.overflowing_add(rhs))
13    }
14});
15
16impl_for_ints!(OptionWrappingAdd, {
17    type Output = Self;
18    fn opt_wrapping_add(self, rhs: Self) -> Option<Self::Output> {
19        Some(self.wrapping_add(rhs))
20    }
21});
22
23option_op_checked!(Add, add, addition);
24
25impl_for_ints_and_duration!(OptionCheckedAdd, {
26    type Output = Self;
27    fn opt_checked_add(self, rhs: Self) -> Result<Option<Self::Output>, Error> {
28        self.checked_add(rhs).ok_or(Error::Overflow).map(Some)
29    }
30});
31
32#[cfg(feature = "std")]
33impl OptionCheckedAdd<std::time::Duration> for std::time::Instant {
34    type Output = Self;
35    fn opt_checked_add(self, rhs: std::time::Duration) -> Result<Option<Self::Output>, Error> {
36        self.checked_add(rhs).ok_or(Error::Overflow).map(Some)
37    }
38}
39
40#[cfg(feature = "std")]
41impl OptionCheckedAdd<std::time::Duration> for std::time::SystemTime {
42    type Output = Self;
43    fn opt_checked_add(self, rhs: std::time::Duration) -> Result<Option<Self::Output>, Error> {
44        self.checked_add(rhs).ok_or(Error::Overflow).map(Some)
45    }
46}
47
48option_op_saturating!(Add, add, addition);
49
50impl_for_ints_and_duration!(OptionSaturatingAdd, {
51    type Output = Self;
52    fn opt_saturating_add(self, rhs: Self) -> Option<Self::Output> {
53        Some(self.saturating_add(rhs))
54    }
55});
56
57#[cfg(test)]
58mod test {
59    use super::*;
60    use crate::OptionOperations;
61    use core::ops::{Add, AddAssign};
62
63    #[derive(Copy, Clone, Debug, PartialEq, PartialOrd)]
64    struct MyInt(u64);
65
66    impl OptionOperations for MyInt {}
67
68    impl Add<MyInt> for MyInt {
69        type Output = MyInt;
70
71        fn add(self, rhs: MyInt) -> MyInt {
72            MyInt(self.0.add(rhs.0))
73        }
74    }
75
76    impl Add<u64> for MyInt {
77        type Output = MyInt;
78
79        fn add(self, rhs: u64) -> MyInt {
80            MyInt(self.0.add(rhs))
81        }
82    }
83
84    impl AddAssign<MyInt> for MyInt {
85        fn add_assign(&mut self, rhs: MyInt) {
86            self.0.add_assign(rhs.0)
87        }
88    }
89
90    impl AddAssign<u64> for MyInt {
91        fn add_assign(&mut self, rhs: u64) {
92            self.0.add_assign(rhs)
93        }
94    }
95
96    const MY_0: MyInt = MyInt(0);
97    const MY_1: MyInt = MyInt(1);
98    const MY_2: MyInt = MyInt(2);
99    const MY_MAX: MyInt = MyInt(u64::MAX);
100    const SOME_0: Option<MyInt> = Some(MY_0);
101    const SOME_1: Option<MyInt> = Some(MY_1);
102    const SOME_2: Option<MyInt> = Some(MY_2);
103    const SOME_MAX: Option<MyInt> = Some(MY_MAX);
104    const NONE: Option<MyInt> = None;
105
106    #[test]
107    fn add_my() {
108        assert_eq!(MY_1.opt_add(MY_1), SOME_2);
109        assert_eq!(SOME_1.opt_add(MY_1), SOME_2);
110        assert_eq!(MY_1.opt_add(SOME_1), SOME_2);
111        assert_eq!(MY_1.opt_add(&SOME_1), SOME_2);
112        assert_eq!(MY_1.opt_add(NONE), NONE);
113        assert_eq!(NONE.opt_add(MY_1), NONE);
114    }
115
116    #[test]
117    fn add_u64() {
118        assert_eq!(MY_1.opt_add(1), SOME_2);
119        assert_eq!(MY_1.opt_add(Some(1)), SOME_2);
120        assert_eq!(SOME_1.opt_add(1), SOME_2);
121        assert_eq!(SOME_1.opt_add(Some(1)), SOME_2);
122        assert_eq!(SOME_1.opt_add(&Some(1)), SOME_2);
123        assert_eq!(MY_1.opt_add(Option::<u64>::None), NONE);
124        assert_eq!(Option::<MyInt>::None.opt_add(MY_0), NONE);
125    }
126
127    #[test]
128    fn add_assign_my() {
129        let mut my = MY_1;
130        my.opt_add_assign(MY_1);
131        assert_eq!(my, MY_2);
132
133        let mut some = SOME_1;
134        some.opt_add_assign(MY_1);
135        assert_eq!(some, SOME_2);
136
137        let mut my = MY_1;
138        my.opt_add_assign(SOME_1);
139        assert_eq!(my, MY_2);
140
141        let mut my = MY_1;
142        my.opt_add_assign(&SOME_1);
143        assert_eq!(my, MY_2);
144
145        let mut my = MY_1;
146        my.opt_add_assign(NONE);
147        assert_eq!(my, MY_1);
148
149        let mut some = SOME_1;
150        some.opt_add_assign(SOME_1);
151        assert_eq!(some, SOME_2);
152
153        let mut some = SOME_1;
154        some.opt_add_assign(&SOME_1);
155        assert_eq!(some, SOME_2);
156
157        let mut some = SOME_1;
158        some.opt_add_assign(NONE);
159        assert_eq!(some, SOME_1);
160
161        let mut none = NONE;
162        none.opt_add_assign(SOME_1);
163        assert_eq!(none, NONE);
164
165        let mut none = NONE;
166        none.opt_add_assign(NONE);
167        assert_eq!(none, NONE);
168    }
169
170    #[test]
171    fn add_assign_u64() {
172        let mut my = MY_1;
173        my.opt_add_assign(1);
174        assert_eq!(my, MY_2);
175
176        let mut some = SOME_1;
177        some.opt_add_assign(1);
178        assert_eq!(some, SOME_2);
179
180        let mut my = MY_1;
181        my.opt_add_assign(Some(1));
182        assert_eq!(my, MY_2);
183
184        let mut my = MY_1;
185        my.opt_add_assign(&Some(1));
186        assert_eq!(my, MY_2);
187
188        let mut some = SOME_1;
189        some.opt_add_assign(Some(1));
190        assert_eq!(some, SOME_2);
191
192        let mut some = SOME_1;
193        some.opt_add_assign(&Some(1));
194        assert_eq!(some, SOME_2);
195
196        let mut none = NONE;
197        none.opt_add_assign(Some(1));
198        assert_eq!(none, NONE);
199    }
200
201    #[test]
202    fn checked_add() {
203        impl OptionCheckedAdd for MyInt {
204            type Output = MyInt;
205            fn opt_checked_add(self, rhs: MyInt) -> Result<Option<Self::Output>, Error> {
206                self.0.opt_checked_add(rhs.0).map(|ok| ok.map(MyInt))
207            }
208        }
209
210        impl OptionCheckedAdd<u64> for MyInt {
211            type Output = MyInt;
212            fn opt_checked_add(self, rhs: u64) -> Result<Option<Self::Output>, Error> {
213                self.0.opt_checked_add(rhs).map(|ok| ok.map(MyInt))
214            }
215        }
216
217        assert_eq!(MY_1.opt_checked_add(MY_1), Ok(SOME_2));
218        assert_eq!(MY_1.opt_checked_add(SOME_1), Ok(SOME_2));
219        assert_eq!(MY_1.opt_checked_add(&SOME_1), Ok(SOME_2));
220        assert_eq!(MY_MAX.opt_checked_add(MY_1), Err(Error::Overflow));
221
222        assert_eq!(SOME_1.opt_checked_add(MY_1), Ok(SOME_2));
223        assert_eq!(SOME_1.opt_checked_add(SOME_1), Ok(SOME_2));
224        assert_eq!(SOME_1.opt_checked_add(&SOME_1), Ok(SOME_2));
225
226        assert_eq!(SOME_MAX.opt_checked_add(MY_1), Err(Error::Overflow));
227        assert_eq!(SOME_MAX.opt_checked_add(1), Err(Error::Overflow));
228        assert_eq!(SOME_MAX.opt_checked_add(Some(1)), Err(Error::Overflow));
229        assert_eq!(MY_1.opt_checked_add(SOME_MAX), Err(Error::Overflow));
230        assert_eq!(MY_MAX.opt_checked_add(NONE), Ok(None));
231        assert_eq!(NONE.opt_checked_add(SOME_MAX), Ok(None));
232    }
233
234    #[test]
235    fn saturating_add() {
236        impl OptionSaturatingAdd for MyInt {
237            type Output = MyInt;
238            fn opt_saturating_add(self, rhs: MyInt) -> Option<Self::Output> {
239                self.0.opt_saturating_add(rhs.0).map(MyInt)
240            }
241        }
242
243        impl OptionSaturatingAdd<u64> for MyInt {
244            type Output = MyInt;
245            fn opt_saturating_add(self, rhs: u64) -> Option<Self::Output> {
246                self.0.opt_saturating_add(rhs).map(MyInt)
247            }
248        }
249
250        assert_eq!(MY_1.opt_saturating_add(MY_1), SOME_2);
251        assert_eq!(MY_MAX.opt_saturating_add(MY_1), SOME_MAX);
252        assert_eq!(SOME_MAX.opt_saturating_add(MY_1), SOME_MAX);
253        assert_eq!(SOME_MAX.opt_saturating_add(1), SOME_MAX);
254        assert_eq!(SOME_MAX.opt_saturating_add(Some(1)), SOME_MAX);
255        assert_eq!(SOME_MAX.opt_saturating_add(&Some(1)), SOME_MAX);
256        assert_eq!(MY_1.opt_saturating_add(SOME_MAX), SOME_MAX);
257        assert_eq!(MY_1.opt_saturating_add(&SOME_MAX), SOME_MAX);
258        assert_eq!(MY_MAX.opt_saturating_add(NONE), NONE);
259        assert_eq!(NONE.opt_saturating_add(SOME_MAX), NONE);
260    }
261
262    #[test]
263    fn overflowing_add() {
264        impl OptionOverflowingAdd for MyInt {
265            type Output = MyInt;
266            fn opt_overflowing_add(self, rhs: MyInt) -> Option<(Self::Output, bool)> {
267                self.0
268                    .opt_overflowing_add(rhs.0)
269                    .map(|(val, flag)| (MyInt(val), flag))
270            }
271        }
272
273        impl OptionOverflowingAdd<u64> for MyInt {
274            type Output = MyInt;
275            fn opt_overflowing_add(self, rhs: u64) -> Option<(Self::Output, bool)> {
276                self.0
277                    .opt_overflowing_add(rhs)
278                    .map(|(val, flag)| (MyInt(val), flag))
279            }
280        }
281
282        assert_eq!(MY_1.opt_overflowing_add(MY_1), Some((MY_2, false)));
283        assert_eq!(MY_MAX.opt_overflowing_add(MY_1), Some((MY_0, true)));
284        assert_eq!(SOME_MAX.opt_overflowing_add(MY_1), Some((MY_0, true)));
285        assert_eq!(SOME_MAX.opt_overflowing_add(1), Some((MY_0, true)));
286        assert_eq!(SOME_MAX.opt_overflowing_add(Some(1)), Some((MY_0, true)));
287        assert_eq!(SOME_MAX.opt_overflowing_add(&Some(1)), Some((MY_0, true)));
288        assert_eq!(MY_1.opt_overflowing_add(SOME_MAX), Some((MY_0, true)));
289        assert_eq!(MY_1.opt_overflowing_add(&SOME_MAX), Some((MY_0, true)));
290        assert_eq!(MY_MAX.opt_overflowing_add(NONE), None);
291        assert_eq!(NONE.opt_overflowing_add(SOME_MAX), None);
292    }
293
294    #[test]
295    fn wrapping_add() {
296        impl OptionWrappingAdd for MyInt {
297            type Output = MyInt;
298            fn opt_wrapping_add(self, rhs: MyInt) -> Option<Self::Output> {
299                self.0.opt_wrapping_add(rhs.0).map(MyInt)
300            }
301        }
302
303        impl OptionWrappingAdd<u64> for MyInt {
304            type Output = MyInt;
305            fn opt_wrapping_add(self, rhs: u64) -> Option<Self::Output> {
306                self.0.opt_wrapping_add(rhs).map(MyInt)
307            }
308        }
309
310        assert_eq!(MY_1.opt_wrapping_add(MY_1), SOME_2);
311        assert_eq!(MY_MAX.opt_wrapping_add(MY_1), SOME_0);
312        assert_eq!(SOME_MAX.opt_wrapping_add(MY_1), SOME_0);
313        assert_eq!(SOME_MAX.opt_wrapping_add(1), SOME_0);
314        assert_eq!(SOME_MAX.opt_wrapping_add(Some(1)), SOME_0);
315        assert_eq!(SOME_MAX.opt_wrapping_add(&Some(1)), SOME_0);
316        assert_eq!(MY_1.opt_wrapping_add(SOME_MAX), SOME_0);
317        assert_eq!(MY_1.opt_wrapping_add(&SOME_MAX), SOME_0);
318        assert_eq!(MY_MAX.opt_wrapping_add(NONE), NONE);
319        assert_eq!(NONE.opt_wrapping_add(SOME_MAX), NONE);
320    }
321}