1 | //! Traits for the division [`OptionOperations`]. |
2 | |
3 | use core::ops::{Div, DivAssign}; |
4 | |
5 | use crate::{Error, OptionOperations}; |
6 | |
7 | common_option_op!( |
8 | Div, |
9 | div, |
10 | division, |
11 | " |
12 | # Panics |
13 | |
14 | Most implementations will panic if `rhs` is zero. |
15 | " , |
16 | ); |
17 | |
18 | impl_for_ints!(OptionOverflowingDiv, { |
19 | type Output = Self; |
20 | fn opt_overflowing_div(self, rhs: Self) -> Option<(Self::Output, bool)> { |
21 | Some(self.overflowing_div(rhs)) |
22 | } |
23 | }); |
24 | |
25 | impl_for_ints!(OptionWrappingDiv, { |
26 | type Output = Self; |
27 | fn opt_wrapping_div(self, rhs: Self) -> Option<Self::Output> { |
28 | Some(self.wrapping_div(rhs)) |
29 | } |
30 | }); |
31 | |
32 | option_op_checked!( |
33 | Div, |
34 | div, |
35 | division, |
36 | "- Returns `Err(Error::DivisionByZero)` if `rhs` is zero." , |
37 | ); |
38 | |
39 | impl_for_ints!(OptionCheckedDiv, { |
40 | type Output = Self; |
41 | fn opt_checked_div(self, rhs: Self) -> Result<Option<Self::Output>, Error> { |
42 | if rhs == 0 { |
43 | return Err(Error::DivisionByZero); |
44 | } |
45 | self.checked_div(rhs).ok_or(Error::Overflow).map(Some) |
46 | } |
47 | }); |
48 | |
49 | impl OptionCheckedDiv<u32> for core::time::Duration { |
50 | type Output = Self; |
51 | fn opt_checked_div(self, rhs: u32) -> Result<Option<Self::Output>, Error> { |
52 | if rhs == 0 { |
53 | return Err(Error::DivisionByZero); |
54 | } |
55 | self.checked_div(rhs).ok_or(Error::Overflow).map(op:Some) |
56 | } |
57 | } |
58 | |
59 | #[cfg (test)] |
60 | mod test { |
61 | use super::*; |
62 | use crate::OptionOperations; |
63 | use core::ops::{Div, DivAssign}; |
64 | |
65 | #[derive (Copy, Clone, Debug, PartialEq, PartialOrd)] |
66 | struct MyInt(i64); |
67 | |
68 | impl OptionOperations for MyInt {} |
69 | |
70 | impl Div<MyInt> for MyInt { |
71 | type Output = MyInt; |
72 | |
73 | fn div(self, rhs: MyInt) -> MyInt { |
74 | MyInt(self.0.div(rhs.0)) |
75 | } |
76 | } |
77 | |
78 | impl Div<i64> for MyInt { |
79 | type Output = MyInt; |
80 | |
81 | fn div(self, rhs: i64) -> MyInt { |
82 | MyInt(self.0.div(rhs)) |
83 | } |
84 | } |
85 | |
86 | impl DivAssign<MyInt> for MyInt { |
87 | fn div_assign(&mut self, rhs: MyInt) { |
88 | self.0.div_assign(rhs.0) |
89 | } |
90 | } |
91 | |
92 | impl DivAssign<i64> for MyInt { |
93 | fn div_assign(&mut self, rhs: i64) { |
94 | self.0.div_assign(rhs) |
95 | } |
96 | } |
97 | |
98 | const MY_MINUS_1: MyInt = MyInt(-1); |
99 | const MY_0: MyInt = MyInt(0); |
100 | const MY_1: MyInt = MyInt(1); |
101 | const MY_2: MyInt = MyInt(2); |
102 | const MY_5: MyInt = MyInt(5); |
103 | const MY_10: MyInt = MyInt(10); |
104 | const MY_MIN: MyInt = MyInt(i64::MIN); |
105 | const MY_HALF_MAX: MyInt = MyInt(i64::MAX / 2); |
106 | const MY_MAX: MyInt = MyInt(i64::MAX); |
107 | const SOME_MINUS_1: Option<MyInt> = Some(MY_MINUS_1); |
108 | const SOME_0: Option<MyInt> = Some(MY_0); |
109 | const SOME_1: Option<MyInt> = Some(MY_1); |
110 | const SOME_2: Option<MyInt> = Some(MY_2); |
111 | const SOME_5: Option<MyInt> = Some(MY_5); |
112 | const SOME_10: Option<MyInt> = Some(MY_10); |
113 | const SOME_MIN: Option<MyInt> = Some(MY_MIN); |
114 | const SOME_HALF_MAX: Option<MyInt> = Some(MY_HALF_MAX); |
115 | const SOME_MAX: Option<MyInt> = Some(MY_MAX); |
116 | const NONE: Option<MyInt> = None; |
117 | |
118 | #[test ] |
119 | fn div_my() { |
120 | assert_eq!(MY_5.opt_div(MY_1), SOME_5); |
121 | assert_eq!(SOME_10.opt_div(MY_2), SOME_5); |
122 | assert_eq!(MY_0.opt_div(SOME_1), SOME_0); |
123 | assert_eq!(MY_MAX.opt_div(&SOME_2), SOME_HALF_MAX); |
124 | assert_eq!(MY_1.opt_div(NONE), NONE); |
125 | assert_eq!(NONE.opt_div(MY_1), NONE); |
126 | } |
127 | |
128 | #[test ] |
129 | #[should_panic ] |
130 | fn div_by_zero_my() { |
131 | let _ = SOME_10.opt_div(SOME_0); |
132 | } |
133 | |
134 | #[test ] |
135 | fn div_i64() { |
136 | assert_eq!(MY_5.opt_div(5), SOME_1); |
137 | assert_eq!(SOME_10.opt_div(MY_2), SOME_5); |
138 | assert_eq!(MY_0.opt_div(Some(1)), SOME_0); |
139 | assert_eq!(MY_MAX.opt_div(Some(2)), SOME_HALF_MAX); |
140 | assert_eq!(MY_1.opt_div(Option::<i64>::None), NONE); |
141 | assert_eq!(Option::<MyInt>::None.opt_div(MY_1), NONE); |
142 | } |
143 | |
144 | #[test ] |
145 | #[should_panic ] |
146 | fn div_by_zero_i64() { |
147 | let _ = SOME_10.opt_div(Some(0)); |
148 | } |
149 | |
150 | #[test ] |
151 | fn div_assign_my() { |
152 | let mut my = MY_5; |
153 | my.opt_div_assign(MY_1); |
154 | assert_eq!(my, MY_5); |
155 | |
156 | let mut some = SOME_10; |
157 | some.opt_div_assign(MY_5); |
158 | assert_eq!(some, SOME_2); |
159 | |
160 | let mut my = MY_0; |
161 | my.opt_div_assign(SOME_1); |
162 | assert_eq!(my, MY_0); |
163 | |
164 | let mut my = MY_MAX; |
165 | my.opt_div_assign(&SOME_2); |
166 | assert_eq!(my, MY_HALF_MAX); |
167 | |
168 | let mut my = MY_1; |
169 | my.opt_div_assign(NONE); |
170 | assert_eq!(my, MY_1); |
171 | |
172 | let mut some = SOME_2; |
173 | some.opt_div_assign(SOME_1); |
174 | assert_eq!(some, SOME_2); |
175 | |
176 | let mut some = SOME_10; |
177 | some.opt_div_assign(&SOME_2); |
178 | assert_eq!(some, SOME_5); |
179 | |
180 | let mut some = SOME_1; |
181 | some.opt_div_assign(NONE); |
182 | assert_eq!(some, SOME_1); |
183 | |
184 | let mut none = NONE; |
185 | none.opt_div_assign(SOME_1); |
186 | assert_eq!(none, NONE); |
187 | |
188 | let mut none = NONE; |
189 | none.opt_div_assign(NONE); |
190 | assert_eq!(none, NONE); |
191 | } |
192 | |
193 | #[test ] |
194 | #[should_panic ] |
195 | fn div_assign_by_zero_my() { |
196 | let mut some = SOME_10; |
197 | some.opt_div_assign(SOME_0); |
198 | } |
199 | |
200 | #[test ] |
201 | fn div_assign_i64() { |
202 | let mut my = MY_5; |
203 | my.opt_div_assign(1); |
204 | assert_eq!(my, MY_5); |
205 | |
206 | let mut some = SOME_10; |
207 | some.opt_div_assign(5); |
208 | assert_eq!(some, SOME_2); |
209 | |
210 | let mut my = MY_0; |
211 | my.opt_div_assign(1); |
212 | assert_eq!(my, MY_0); |
213 | |
214 | let mut my = MY_MAX; |
215 | my.opt_div_assign(2); |
216 | assert_eq!(my, MY_HALF_MAX); |
217 | |
218 | let mut my = MY_1; |
219 | my.opt_div_assign(Option::<i64>::None); |
220 | assert_eq!(my, MY_1); |
221 | |
222 | let mut some = SOME_2; |
223 | some.opt_div_assign(1); |
224 | assert_eq!(some, SOME_2); |
225 | |
226 | let mut some = SOME_1; |
227 | some.opt_div_assign(Option::<i64>::None); |
228 | assert_eq!(some, SOME_1); |
229 | |
230 | let mut none = NONE; |
231 | none.opt_div_assign(1); |
232 | assert_eq!(none, NONE); |
233 | |
234 | let mut none = NONE; |
235 | none.opt_div_assign(Option::<i64>::None); |
236 | assert_eq!(none, NONE); |
237 | } |
238 | |
239 | #[test ] |
240 | #[should_panic ] |
241 | fn div_assign_by_zero_i64() { |
242 | let mut some = SOME_10; |
243 | some.opt_div_assign(Some(0)); |
244 | } |
245 | |
246 | #[test ] |
247 | fn checked_div() { |
248 | impl OptionCheckedDiv for MyInt { |
249 | type Output = MyInt; |
250 | fn opt_checked_div(self, rhs: MyInt) -> Result<Option<Self::Output>, Error> { |
251 | self.0.opt_checked_div(rhs.0).map(|ok| ok.map(MyInt)) |
252 | } |
253 | } |
254 | |
255 | impl OptionCheckedDiv<i64> for MyInt { |
256 | type Output = MyInt; |
257 | fn opt_checked_div(self, rhs: i64) -> Result<Option<Self::Output>, Error> { |
258 | self.0.opt_checked_div(rhs).map(|ok| ok.map(MyInt)) |
259 | } |
260 | } |
261 | |
262 | assert_eq!(MY_2.opt_checked_div(MY_1), Ok(SOME_2)); |
263 | assert_eq!(MY_10.opt_checked_div(SOME_5), Ok(SOME_2)); |
264 | assert_eq!(MY_0.opt_checked_div(&SOME_1), Ok(SOME_0)); |
265 | assert_eq!(MY_MAX.opt_checked_div(MY_2), Ok(SOME_HALF_MAX)); |
266 | assert_eq!(MY_MAX.opt_checked_div(MY_0), Err(Error::DivisionByZero)); |
267 | assert_eq!(MY_MIN.opt_checked_div(MY_MINUS_1), Err(Error::Overflow)); |
268 | |
269 | assert_eq!(SOME_2.opt_checked_div(MY_1), Ok(SOME_2)); |
270 | assert_eq!(SOME_10.opt_checked_div(SOME_2), Ok(SOME_5)); |
271 | assert_eq!(SOME_0.opt_checked_div(&SOME_1), Ok(SOME_0)); |
272 | |
273 | assert_eq!(SOME_MAX.opt_checked_div(MY_2), Ok(SOME_HALF_MAX)); |
274 | assert_eq!(SOME_MAX.opt_checked_div(MY_0), Err(Error::DivisionByZero)); |
275 | assert_eq!(SOME_MIN.opt_checked_div(MY_MINUS_1), Err(Error::Overflow)); |
276 | assert_eq!(SOME_MAX.opt_checked_div(0), Err(Error::DivisionByZero)); |
277 | assert_eq!(SOME_MIN.opt_checked_div(-1), Err(Error::Overflow)); |
278 | assert_eq!( |
279 | SOME_MAX.opt_checked_div(Some(0)), |
280 | Err(Error::DivisionByZero) |
281 | ); |
282 | assert_eq!(SOME_MIN.opt_checked_div(Some(-1)), Err(Error::Overflow)); |
283 | assert_eq!(SOME_MAX.opt_checked_div(SOME_0), Err(Error::DivisionByZero)); |
284 | assert_eq!(SOME_MIN.opt_checked_div(SOME_MINUS_1), Err(Error::Overflow)); |
285 | assert_eq!(MY_MIN.opt_checked_div(NONE), Ok(None)); |
286 | assert_eq!(NONE.opt_checked_div(SOME_MIN), Ok(None)); |
287 | } |
288 | |
289 | #[test ] |
290 | fn overflowing_div() { |
291 | impl OptionOverflowingDiv for MyInt { |
292 | type Output = MyInt; |
293 | fn opt_overflowing_div(self, rhs: MyInt) -> Option<(Self::Output, bool)> { |
294 | self.0 |
295 | .opt_overflowing_div(rhs.0) |
296 | .map(|(val, flag)| (MyInt(val), flag)) |
297 | } |
298 | } |
299 | |
300 | impl OptionOverflowingDiv<i64> for MyInt { |
301 | type Output = MyInt; |
302 | fn opt_overflowing_div(self, rhs: i64) -> Option<(Self::Output, bool)> { |
303 | self.0 |
304 | .opt_overflowing_div(rhs) |
305 | .map(|(val, flag)| (MyInt(val), flag)) |
306 | } |
307 | } |
308 | |
309 | assert_eq!(MY_2.opt_overflowing_div(MY_1), Some((MY_2, false))); |
310 | assert_eq!(MY_0.opt_overflowing_div(MY_1), Some((MY_0, false))); |
311 | assert_eq!(MY_MAX.opt_overflowing_div(MY_2), Some((MY_HALF_MAX, false))); |
312 | assert_eq!(MY_MIN.opt_overflowing_div(MY_MINUS_1), Some((MY_MIN, true))); |
313 | assert_eq!( |
314 | SOME_MIN.opt_overflowing_div(MY_MINUS_1), |
315 | Some((MY_MIN, true)) |
316 | ); |
317 | assert_eq!(SOME_MIN.opt_overflowing_div(-1), Some((MY_MIN, true))); |
318 | assert_eq!(SOME_MIN.opt_overflowing_div(Some(-1)), Some((MY_MIN, true))); |
319 | assert_eq!( |
320 | SOME_MIN.opt_overflowing_div(&Some(-1)), |
321 | Some((MY_MIN, true)) |
322 | ); |
323 | assert_eq!( |
324 | MY_MIN.opt_overflowing_div(SOME_MINUS_1), |
325 | Some((MY_MIN, true)) |
326 | ); |
327 | assert_eq!( |
328 | MY_MIN.opt_overflowing_div(&SOME_MINUS_1), |
329 | Some((MY_MIN, true)) |
330 | ); |
331 | assert_eq!(MY_MIN.opt_overflowing_div(NONE), None); |
332 | assert_eq!(NONE.opt_overflowing_div(MY_MIN), None); |
333 | } |
334 | |
335 | #[test ] |
336 | fn wrapping_div() { |
337 | impl OptionWrappingDiv for MyInt { |
338 | type Output = MyInt; |
339 | fn opt_wrapping_div(self, rhs: MyInt) -> Option<Self::Output> { |
340 | self.0.opt_wrapping_div(rhs.0).map(MyInt) |
341 | } |
342 | } |
343 | |
344 | impl OptionWrappingDiv<i64> for MyInt { |
345 | type Output = MyInt; |
346 | fn opt_wrapping_div(self, rhs: i64) -> Option<Self::Output> { |
347 | self.0.opt_wrapping_div(rhs).map(MyInt) |
348 | } |
349 | } |
350 | |
351 | assert_eq!(MY_2.opt_wrapping_div(MY_1), SOME_2); |
352 | assert_eq!(MY_0.opt_wrapping_div(MY_1), SOME_0); |
353 | assert_eq!(MY_MIN.opt_wrapping_div(MY_MINUS_1), SOME_MIN); |
354 | assert_eq!(SOME_MIN.opt_wrapping_div(MY_MINUS_1), SOME_MIN); |
355 | assert_eq!(SOME_MIN.opt_wrapping_div(-1), SOME_MIN); |
356 | assert_eq!(SOME_MIN.opt_wrapping_div(Some(-1)), SOME_MIN); |
357 | assert_eq!(SOME_MIN.opt_wrapping_div(&Some(-1)), SOME_MIN); |
358 | assert_eq!(MY_MIN.opt_wrapping_div(SOME_MINUS_1), SOME_MIN); |
359 | assert_eq!(MY_MIN.opt_wrapping_div(&SOME_MINUS_1), SOME_MIN); |
360 | assert_eq!(MY_MIN.opt_wrapping_div(NONE), None); |
361 | assert_eq!(NONE.opt_wrapping_div(MY_MIN), None); |
362 | } |
363 | } |
364 | |