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(op: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}
364