option_operations/
mul.rs

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