1 | //! Traits for the remainder [`OptionOperations`]. |
2 | |
3 | use core::ops::{Rem, RemAssign}; |
4 | |
5 | use crate::{Error, OptionOperations}; |
6 | |
7 | common_option_op!( |
8 | Rem, |
9 | rem, |
10 | remainder, |
11 | " |
12 | # Panics |
13 | |
14 | Most implementations will panic if `rhs` is zero. |
15 | " , |
16 | ); |
17 | |
18 | impl_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 | |
25 | impl_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 | |
32 | option_op_checked!( |
33 | Rem, |
34 | rem, |
35 | remainder, |
36 | "- Returns `Err(Error::DivisionByZero)` if `rhs` is zero." , |
37 | ); |
38 | |
39 | impl_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)] |
50 | mod 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 | |