option_operations/
div.rs

1//! Traits for the division [`OptionOperations`].
2
3use core::ops::{Div, DivAssign};
4
5use crate::{Error, OptionOperations};
6
7common_option_op!(
8    Div,
9    div,
10    division,
11    "
12# Panics
13
14Most implementations will panic if `rhs` is zero.
15",
16);
17
18impl_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
25impl_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
32option_op_checked!(
33    Div,
34    div,
35    division,
36    "- Returns `Err(Error::DivisionByZero)` if `rhs` is zero.",
37);
38
39impl_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
49impl 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(Some)
56    }
57}
58
59#[cfg(test)]
60mod 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}