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    impl OptionCheckedMul for MyInt {
95        type Output = MyInt;
96        fn opt_checked_mul(self, rhs: MyInt) -> Result<Option<Self::Output>, Error> {
97            self.0.opt_checked_mul(rhs.0).map(|ok| ok.map(MyInt))
98        }
99    }
100
101    impl OptionCheckedMul<u64> for MyInt {
102        type Output = MyInt;
103        fn opt_checked_mul(self, rhs: u64) -> Result<Option<Self::Output>, Error> {
104            self.0.opt_checked_mul(rhs).map(|ok| ok.map(MyInt))
105        }
106    }
107
108    impl OptionSaturatingMul for MyInt {
109        type Output = MyInt;
110        fn opt_saturating_mul(self, rhs: MyInt) -> Option<Self::Output> {
111            self.0.opt_saturating_mul(rhs.0).map(MyInt)
112        }
113    }
114
115    impl OptionSaturatingMul<u64> for MyInt {
116        type Output = MyInt;
117        fn opt_saturating_mul(self, rhs: u64) -> Option<Self::Output> {
118            self.0.opt_saturating_mul(rhs).map(MyInt)
119        }
120    }
121
122    impl OptionOverflowingMul for MyInt {
123        type Output = MyInt;
124        fn opt_overflowing_mul(self, rhs: MyInt) -> Option<(Self::Output, bool)> {
125            self.0
126                .opt_overflowing_mul(rhs.0)
127                .map(|(val, flag)| (MyInt(val), flag))
128        }
129    }
130
131    impl OptionOverflowingMul<u64> for MyInt {
132        type Output = MyInt;
133        fn opt_overflowing_mul(self, rhs: u64) -> Option<(Self::Output, bool)> {
134            self.0
135                .opt_overflowing_mul(rhs)
136                .map(|(val, flag)| (MyInt(val), flag))
137        }
138    }
139
140    impl OptionWrappingMul for MyInt {
141        type Output = MyInt;
142        fn opt_wrapping_mul(self, rhs: MyInt) -> Option<Self::Output> {
143            self.0.opt_wrapping_mul(rhs.0).map(MyInt)
144        }
145    }
146
147    impl OptionWrappingMul<u64> for MyInt {
148        type Output = MyInt;
149        fn opt_wrapping_mul(self, rhs: u64) -> Option<Self::Output> {
150            self.0.opt_wrapping_mul(rhs).map(MyInt)
151        }
152    }
153
154    const MY_0: MyInt = MyInt(0);
155    const MY_1: MyInt = MyInt(1);
156    const MY_2: MyInt = MyInt(2);
157    const MY_5: MyInt = MyInt(5);
158    const MY_10: MyInt = MyInt(10);
159    const MY_HALF_MAX: MyInt = MyInt(u64::MAX / 2);
160    const MY_MAX_MINUS_1: MyInt = MyInt(u64::MAX - 1);
161    // u64::MAX is an odd nb, so (u64::MAX / 2) * 2 == (u64::MAX - 1)
162    const MY_MAX: MyInt = MyInt(u64::MAX);
163    const SOME_0: Option<MyInt> = Some(MY_0);
164    const SOME_1: Option<MyInt> = Some(MY_1);
165    const SOME_2: Option<MyInt> = Some(MY_2);
166    const SOME_5: Option<MyInt> = Some(MY_5);
167    const SOME_10: Option<MyInt> = Some(MY_10);
168    const SOME_HALF_MAX: Option<MyInt> = Some(MY_HALF_MAX);
169    const SOME_MAX_MINUS_1: Option<MyInt> = Some(MY_MAX_MINUS_1);
170    const SOME_MAX: Option<MyInt> = Some(MY_MAX);
171    const NONE: Option<MyInt> = None;
172
173    #[test]
174    fn mul_my() {
175        assert_eq!(MY_1.opt_mul(MY_5), SOME_5);
176        assert_eq!(SOME_2.opt_mul(MY_5), SOME_10);
177        assert_eq!(MY_0.opt_mul(SOME_1), SOME_0);
178        // See comment in the const definitions
179        assert_eq!(MY_HALF_MAX.opt_mul(&SOME_2), SOME_MAX_MINUS_1);
180        assert_eq!(MY_1.opt_mul(NONE), NONE);
181        assert_eq!(NONE.opt_mul(MY_1), NONE);
182    }
183
184    #[test]
185    fn mul_u64() {
186        assert_eq!(MY_1.opt_mul(5), SOME_5);
187        assert_eq!(SOME_2.opt_mul(5), SOME_10);
188        assert_eq!(MY_0.opt_mul(Some(1)), SOME_0);
189        // See comment in the const definitions
190        assert_eq!(MY_HALF_MAX.opt_mul(Some(2)), SOME_MAX_MINUS_1);
191        assert_eq!(MY_1.opt_mul(Option::<u64>::None), NONE);
192        assert_eq!(Option::<MyInt>::None.opt_mul(MY_1), NONE);
193    }
194
195    #[test]
196    fn mul_assign_my() {
197        let mut my = MY_1;
198        my.opt_mul_assign(MY_5);
199        assert_eq!(my, MY_5);
200
201        let mut some = SOME_2;
202        some.opt_mul_assign(MY_5);
203        assert_eq!(some, SOME_10);
204
205        let mut my = MY_0;
206        my.opt_mul_assign(SOME_1);
207        assert_eq!(my, MY_0);
208
209        // See comment in the const definitions
210        let mut my = MY_HALF_MAX;
211        my.opt_mul_assign(&SOME_2);
212        assert_eq!(my, MY_MAX_MINUS_1);
213
214        let mut my = MY_1;
215        my.opt_mul_assign(NONE);
216        assert_eq!(my, MY_1);
217
218        let mut some = SOME_1;
219        some.opt_mul_assign(SOME_2);
220        assert_eq!(some, SOME_2);
221
222        let mut some = SOME_5;
223        some.opt_mul_assign(&SOME_2);
224        assert_eq!(some, SOME_10);
225
226        let mut some = SOME_1;
227        some.opt_mul_assign(NONE);
228        assert_eq!(some, SOME_1);
229
230        let mut none = NONE;
231        none.opt_mul_assign(SOME_1);
232        assert_eq!(none, NONE);
233
234        let mut none = NONE;
235        none.opt_mul_assign(NONE);
236        assert_eq!(none, NONE);
237    }
238
239    #[test]
240    fn mul_assign_u64() {
241        let mut my = MY_1;
242        my.opt_mul_assign(5);
243        assert_eq!(my, MY_5);
244
245        let mut some = SOME_2;
246        some.opt_mul_assign(5);
247        assert_eq!(some, SOME_10);
248
249        let mut my = MY_0;
250        my.opt_mul_assign(1);
251        assert_eq!(my, MY_0);
252
253        // See comment in the const definitions
254        let mut my = MY_HALF_MAX;
255        my.opt_mul_assign(2);
256        assert_eq!(my, MY_MAX_MINUS_1);
257
258        let mut my = MY_1;
259        my.opt_mul_assign(Option::<u64>::None);
260        assert_eq!(my, MY_1);
261
262        let mut some = SOME_1;
263        some.opt_mul_assign(2);
264        assert_eq!(some, SOME_2);
265
266        let mut some = SOME_1;
267        some.opt_mul_assign(Option::<u64>::None);
268        assert_eq!(some, SOME_1);
269
270        let mut none = NONE;
271        none.opt_mul_assign(1);
272        assert_eq!(none, NONE);
273
274        let mut none = NONE;
275        none.opt_mul_assign(Option::<u64>::None);
276        assert_eq!(none, NONE);
277    }
278
279    #[test]
280    fn checked_mul() {
281        assert_eq!(MY_1.opt_checked_mul(MY_2), Ok(SOME_2));
282        assert_eq!(MY_2.opt_checked_mul(SOME_5), Ok(SOME_10));
283        assert_eq!(MY_1.opt_checked_mul(&SOME_0), Ok(SOME_0));
284        assert_eq!(MY_HALF_MAX.opt_checked_mul(MY_2), Ok(SOME_MAX_MINUS_1));
285        assert_eq!(MY_HALF_MAX.opt_checked_mul(MY_5), Err(Error::Overflow));
286
287        assert_eq!(SOME_1.opt_checked_mul(MY_2), Ok(SOME_2));
288        assert_eq!(SOME_2.opt_checked_mul(SOME_5), Ok(SOME_10));
289        assert_eq!(SOME_1.opt_checked_mul(&SOME_0), Ok(SOME_0));
290
291        assert_eq!(SOME_HALF_MAX.opt_checked_mul(MY_2), Ok(SOME_MAX_MINUS_1));
292        assert_eq!(SOME_HALF_MAX.opt_checked_mul(MY_5), Err(Error::Overflow));
293        assert_eq!(SOME_MAX.opt_checked_mul(2), Err(Error::Overflow));
294        assert_eq!(SOME_HALF_MAX.opt_checked_mul(Some(5)), Err(Error::Overflow));
295        assert_eq!(SOME_MAX.opt_checked_mul(SOME_2), Err(Error::Overflow));
296        assert_eq!(MY_MAX.opt_checked_mul(NONE), Ok(None));
297        assert_eq!(NONE.opt_checked_mul(SOME_MAX), Ok(None));
298    }
299
300    #[test]
301    fn saturating_mul() {
302        assert_eq!(MY_1.opt_saturating_mul(MY_2), SOME_2);
303        assert_eq!(MY_0.opt_saturating_mul(MY_2), SOME_0);
304        assert_eq!(MY_MAX.opt_saturating_mul(MY_2), SOME_MAX);
305        assert_eq!(SOME_MAX.opt_saturating_mul(MY_2), SOME_MAX);
306        assert_eq!(SOME_MAX.opt_saturating_mul(2), SOME_MAX);
307        assert_eq!(SOME_MAX.opt_saturating_mul(Some(2)), SOME_MAX);
308        assert_eq!(SOME_MAX.opt_saturating_mul(&Some(2)), SOME_MAX);
309        assert_eq!(MY_2.opt_saturating_mul(SOME_MAX), SOME_MAX);
310        assert_eq!(MY_2.opt_saturating_mul(&SOME_MAX), SOME_MAX);
311        assert_eq!(MY_MAX.opt_saturating_mul(NONE), NONE);
312        assert_eq!(NONE.opt_saturating_mul(SOME_MAX), NONE);
313    }
314
315    #[test]
316    fn overflowing_mul() {
317        assert_eq!(MY_1.opt_overflowing_mul(MY_2), Some((MY_2, false)));
318        assert_eq!(MY_1.opt_overflowing_mul(MY_0), Some((MY_0, false)));
319        assert_eq!(
320            MY_MAX.opt_overflowing_mul(MY_2),
321            Some((MY_MAX_MINUS_1, true))
322        );
323        assert_eq!(
324            SOME_MAX.opt_overflowing_mul(MY_2),
325            Some((MY_MAX_MINUS_1, true))
326        );
327        assert_eq!(
328            SOME_MAX.opt_overflowing_mul(2),
329            Some((MY_MAX_MINUS_1, true))
330        );
331        assert_eq!(
332            SOME_MAX.opt_overflowing_mul(Some(2)),
333            Some((MY_MAX_MINUS_1, true))
334        );
335        assert_eq!(
336            SOME_MAX.opt_overflowing_mul(&Some(2)),
337            Some((MY_MAX_MINUS_1, true))
338        );
339        assert_eq!(
340            MY_2.opt_overflowing_mul(SOME_MAX),
341            Some((MY_MAX_MINUS_1, true))
342        );
343        assert_eq!(
344            MY_2.opt_overflowing_mul(&SOME_MAX),
345            Some((MY_MAX_MINUS_1, true))
346        );
347        assert_eq!(MY_MAX.opt_overflowing_mul(NONE), None);
348        assert_eq!(NONE.opt_overflowing_mul(SOME_MAX), None);
349    }
350
351    #[test]
352    fn wrapping_mul() {
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}