option_operations/
rem.rs

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