1 | //! Traits for the addition [`OptionOperations`]. |
2 | |
3 | use core::ops::{Add, AddAssign}; |
4 | |
5 | use crate::{Error, OptionOperations}; |
6 | |
7 | common_option_op!(Add, add, addition); |
8 | |
9 | impl_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 | |
16 | impl_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 | |
23 | option_op_checked!(Add, add, addition); |
24 | |
25 | impl_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" )] |
33 | impl 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(op:Some) |
37 | } |
38 | } |
39 | |
40 | #[cfg (feature = "std" )] |
41 | impl 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(op:Some) |
45 | } |
46 | } |
47 | |
48 | option_op_saturating!(Add, add, addition); |
49 | |
50 | impl_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)] |
58 | mod 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 | } |
322 | |