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}
344