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    impl OptionCheckedRem for MyInt {
89        type Output = MyInt;
90        fn opt_checked_rem(self, rhs: MyInt) -> Result<Option<Self::Output>, Error> {
91            self.0.opt_checked_rem(rhs.0).map(|ok| ok.map(MyInt))
92        }
93    }
94
95    impl OptionCheckedRem<i64> for MyInt {
96        type Output = MyInt;
97        fn opt_checked_rem(self, rhs: i64) -> Result<Option<Self::Output>, Error> {
98            self.0.opt_checked_rem(rhs).map(|ok| ok.map(MyInt))
99        }
100    }
101
102    impl OptionOverflowingRem for MyInt {
103        type Output = MyInt;
104        fn opt_overflowing_rem(self, rhs: MyInt) -> Option<(Self::Output, bool)> {
105            self.0
106                .opt_overflowing_rem(rhs.0)
107                .map(|(val, flag)| (MyInt(val), flag))
108        }
109    }
110
111    impl OptionOverflowingRem<i64> for MyInt {
112        type Output = MyInt;
113        fn opt_overflowing_rem(self, rhs: i64) -> Option<(Self::Output, bool)> {
114            self.0
115                .opt_overflowing_rem(rhs)
116                .map(|(val, flag)| (MyInt(val), flag))
117        }
118    }
119
120    impl OptionWrappingRem for MyInt {
121        type Output = MyInt;
122        fn opt_wrapping_rem(self, rhs: MyInt) -> Option<Self::Output> {
123            self.0.opt_wrapping_rem(rhs.0).map(MyInt)
124        }
125    }
126
127    impl OptionWrappingRem<i64> for MyInt {
128        type Output = MyInt;
129        fn opt_wrapping_rem(self, rhs: i64) -> Option<Self::Output> {
130            self.0.opt_wrapping_rem(rhs).map(MyInt)
131        }
132    }
133
134    const MY_MINUS_1: MyInt = MyInt(-1);
135    const MY_0: MyInt = MyInt(0);
136    const MY_1: MyInt = MyInt(1);
137    const MY_2: MyInt = MyInt(2);
138    const MY_5: MyInt = MyInt(5);
139    const MY_10: MyInt = MyInt(10);
140    const MY_MIN: MyInt = MyInt(i64::MIN);
141    const MY_MAX: MyInt = MyInt(i64::MAX);
142    const SOME_MINUS_1: Option<MyInt> = Some(MY_MINUS_1);
143    const SOME_0: Option<MyInt> = Some(MY_0);
144    const SOME_1: Option<MyInt> = Some(MY_1);
145    const SOME_2: Option<MyInt> = Some(MY_2);
146    const SOME_5: Option<MyInt> = Some(MY_5);
147    const SOME_10: Option<MyInt> = Some(MY_10);
148    const SOME_MIN: Option<MyInt> = Some(MY_MIN);
149    const SOME_MAX: Option<MyInt> = Some(MY_MAX);
150    const NONE: Option<MyInt> = None;
151
152    #[test]
153    fn rem_my() {
154        assert_eq!(MY_5.opt_rem(MY_1), SOME_0);
155        assert_eq!(SOME_5.opt_rem(MY_2), SOME_1);
156        assert_eq!(MY_0.opt_rem(SOME_1), SOME_0);
157        assert_eq!(MY_MAX.opt_rem(&SOME_2), SOME_1);
158        assert_eq!(MY_1.opt_rem(NONE), NONE);
159        assert_eq!(NONE.opt_rem(MY_1), NONE);
160    }
161
162    #[test]
163    #[should_panic]
164    fn rem_by_zero_my() {
165        let _ = SOME_10.opt_rem(SOME_0);
166    }
167
168    #[test]
169    fn rem_i64() {
170        assert_eq!(MY_5.opt_rem(1), SOME_0);
171        assert_eq!(SOME_5.opt_rem(MY_2), SOME_1);
172        assert_eq!(MY_0.opt_rem(Some(1)), SOME_0);
173        assert_eq!(MY_MAX.opt_rem(Some(2)), SOME_1);
174        assert_eq!(MY_1.opt_rem(Option::<i64>::None), NONE);
175        assert_eq!(Option::<MyInt>::None.opt_rem(MY_1), NONE);
176    }
177
178    #[test]
179    #[should_panic]
180    fn rem_by_zero_i64() {
181        let _ = SOME_10.opt_rem(Some(0));
182    }
183
184    #[test]
185    fn rem_assign_my() {
186        let mut my = MY_5;
187        my.opt_rem_assign(MY_1);
188        assert_eq!(my, MY_0);
189
190        let mut some = SOME_5;
191        some.opt_rem_assign(MY_2);
192        assert_eq!(some, SOME_1);
193
194        let mut my = MY_0;
195        my.opt_rem_assign(SOME_1);
196        assert_eq!(my, MY_0);
197
198        let mut my = MY_MAX;
199        my.opt_rem_assign(&SOME_2);
200        assert_eq!(my, MY_1);
201
202        let mut my = MY_1;
203        my.opt_rem_assign(NONE);
204        assert_eq!(my, MY_1);
205
206        let mut some = SOME_2;
207        some.opt_rem_assign(SOME_1);
208        assert_eq!(some, SOME_0);
209
210        let mut some = SOME_5;
211        some.opt_rem_assign(&SOME_2);
212        assert_eq!(some, SOME_1);
213
214        let mut some = SOME_1;
215        some.opt_rem_assign(NONE);
216        assert_eq!(some, SOME_1);
217
218        let mut none = NONE;
219        none.opt_rem_assign(SOME_1);
220        assert_eq!(none, NONE);
221
222        let mut none = NONE;
223        none.opt_rem_assign(NONE);
224        assert_eq!(none, NONE);
225    }
226
227    #[test]
228    #[should_panic]
229    fn rem_assign_by_zero_my() {
230        let mut some = SOME_10;
231        some.opt_rem_assign(SOME_0);
232    }
233
234    #[test]
235    fn rem_assign_i64() {
236        let mut my = MY_5;
237        my.opt_rem_assign(1);
238        assert_eq!(my, MY_0);
239
240        let mut some = SOME_5;
241        some.opt_rem_assign(2);
242        assert_eq!(some, SOME_1);
243
244        let mut my = MY_0;
245        my.opt_rem_assign(1);
246        assert_eq!(my, MY_0);
247
248        let mut my = MY_MAX;
249        my.opt_rem_assign(2);
250        assert_eq!(my, MY_1);
251
252        let mut my = MY_1;
253        my.opt_rem_assign(Option::<i64>::None);
254        assert_eq!(my, MY_1);
255
256        let mut some = SOME_2;
257        some.opt_rem_assign(1);
258        assert_eq!(some, SOME_0);
259
260        let mut some = SOME_1;
261        some.opt_rem_assign(Option::<i64>::None);
262        assert_eq!(some, SOME_1);
263
264        let mut none = NONE;
265        none.opt_rem_assign(1);
266        assert_eq!(none, NONE);
267
268        let mut none = NONE;
269        none.opt_rem_assign(Option::<i64>::None);
270        assert_eq!(none, NONE);
271    }
272
273    #[test]
274    #[should_panic]
275    fn rem_assign_by_zero_i64() {
276        let mut some = SOME_10;
277        some.opt_rem_assign(Some(0));
278    }
279
280    #[test]
281    fn checked_rem() {
282        assert_eq!(MY_2.opt_checked_rem(MY_1), Ok(SOME_0));
283        assert_eq!(MY_5.opt_checked_rem(SOME_2), Ok(SOME_1));
284        assert_eq!(MY_0.opt_checked_rem(&SOME_1), Ok(SOME_0));
285        assert_eq!(MY_MAX.opt_checked_rem(MY_2), Ok(SOME_1));
286        assert_eq!(MY_MAX.opt_checked_rem(MY_0), Err(Error::DivisionByZero));
287        assert_eq!(MY_MIN.opt_checked_rem(MY_MINUS_1), Err(Error::Overflow));
288
289        assert_eq!(SOME_2.opt_checked_rem(MY_1), Ok(SOME_0));
290        assert_eq!(SOME_5.opt_checked_rem(SOME_2), Ok(SOME_1));
291        assert_eq!(SOME_0.opt_checked_rem(&SOME_1), Ok(SOME_0));
292
293        assert_eq!(SOME_MAX.opt_checked_rem(MY_2), Ok(SOME_1));
294        assert_eq!(SOME_MAX.opt_checked_rem(MY_0), Err(Error::DivisionByZero));
295        assert_eq!(SOME_MIN.opt_checked_rem(MY_MINUS_1), Err(Error::Overflow));
296        assert_eq!(SOME_MAX.opt_checked_rem(0), Err(Error::DivisionByZero));
297        assert_eq!(SOME_MIN.opt_checked_rem(-1), Err(Error::Overflow));
298        assert_eq!(
299            SOME_MAX.opt_checked_rem(Some(0)),
300            Err(Error::DivisionByZero)
301        );
302        assert_eq!(SOME_MIN.opt_checked_rem(Some(-1)), Err(Error::Overflow));
303        assert_eq!(SOME_MAX.opt_checked_rem(SOME_0), Err(Error::DivisionByZero));
304        assert_eq!(SOME_MIN.opt_checked_rem(SOME_MINUS_1), Err(Error::Overflow));
305        assert_eq!(MY_MIN.opt_checked_rem(NONE), Ok(None));
306        assert_eq!(NONE.opt_checked_rem(SOME_MIN), Ok(None));
307    }
308
309    #[test]
310    fn overflowing_rem() {
311        assert_eq!(MY_2.opt_overflowing_rem(MY_1), Some((MY_0, false)));
312        assert_eq!(MY_0.opt_overflowing_rem(MY_1), Some((MY_0, false)));
313        assert_eq!(MY_MAX.opt_overflowing_rem(MY_2), Some((MY_1, false)));
314        assert_eq!(MY_MIN.opt_overflowing_rem(MY_MINUS_1), Some((MY_0, true)));
315        assert_eq!(SOME_MIN.opt_overflowing_rem(MY_MINUS_1), Some((MY_0, true)));
316        assert_eq!(SOME_MIN.opt_overflowing_rem(-1), Some((MY_0, true)));
317        assert_eq!(SOME_MIN.opt_overflowing_rem(Some(-1)), Some((MY_0, true)));
318        assert_eq!(SOME_MIN.opt_overflowing_rem(&Some(-1)), Some((MY_0, true)));
319        assert_eq!(MY_MIN.opt_overflowing_rem(SOME_MINUS_1), Some((MY_0, true)));
320        assert_eq!(
321            MY_MIN.opt_overflowing_rem(&SOME_MINUS_1),
322            Some((MY_0, true))
323        );
324        assert_eq!(MY_MIN.opt_overflowing_rem(NONE), None);
325        assert_eq!(NONE.opt_overflowing_rem(MY_MIN), None);
326    }
327
328    #[test]
329    fn wrapping_rem() {
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}