1 | macro_rules! option_op_saturating { |
2 | ($trait:ident, $op:ident, $op_name:ident $(,)?) => { |
3 | paste::paste! { |
4 | #[doc = "Trait for values and `Option`s saturating " $op_name "." ] |
5 | /// |
6 | /// Implementing this trait leads to the following auto-implementations: |
7 | /// |
8 | #[doc = "- `" [<OptionSaturating $trait>] "<Option<InnerRhs>>` for `T`." ] |
9 | #[doc = "- `" [<OptionSaturating $trait>] "<Rhs>` for `Option<T>`." ] |
10 | #[doc = "- `" [<OptionSaturating $trait>] "<Option<InnerRhs>>` for `Option<T>`." ] |
11 | /// - ... and some variants with references. |
12 | /// |
13 | /// Note that since the `std` library doesn't define any |
14 | #[doc = "`" [<Saturating $trait >] "` trait, " ] |
15 | /// users must provide the base implementation for the inner type. |
16 | pub trait [<OptionSaturating $trait>]<Rhs = Self, InnerRhs = Rhs> { |
17 | #[doc = "The resulting inner type after applying the " $op_name "." ] |
18 | type Output; |
19 | |
20 | #[doc = "Computes the " $op_name] |
21 | /// saturating at the numeric bounds instead of overflowing. |
22 | /// |
23 | /// Returns `None` if at least one argument is `None`. |
24 | fn [<opt_saturating_ $op>](self, rhs: Rhs) -> Option<Self::Output>; |
25 | } |
26 | |
27 | impl<T, InnerRhs> [<OptionSaturating $trait>]<Option<InnerRhs>, InnerRhs> for T |
28 | where |
29 | T: OptionOperations + [<OptionSaturating $trait>]<InnerRhs>, |
30 | { |
31 | type Output = <T as [<OptionSaturating $trait>]<InnerRhs>>::Output; |
32 | |
33 | fn [<opt_saturating_ $op>](self, rhs: Option<InnerRhs>) -> Option<Self::Output> { |
34 | rhs.and_then(|inner_rhs| self.[<opt_saturating_ $op>](inner_rhs)) |
35 | } |
36 | } |
37 | |
38 | impl<T, InnerRhs> [<OptionSaturating $trait>]<&Option<InnerRhs>, InnerRhs> for T |
39 | where |
40 | T: OptionOperations + [<OptionSaturating $trait>]<InnerRhs>, |
41 | InnerRhs: Copy, |
42 | { |
43 | type Output = <T as [<OptionSaturating $trait>]<InnerRhs>>::Output; |
44 | |
45 | fn [<opt_saturating_ $op>](self, rhs: &Option<InnerRhs>) -> Option<Self::Output> { |
46 | rhs.as_ref() |
47 | .and_then(|inner_rhs| self.[<opt_saturating_ $op>](*inner_rhs)) |
48 | } |
49 | } |
50 | |
51 | impl<T, Rhs> [<OptionSaturating $trait>]<Rhs> for Option<T> |
52 | where |
53 | T: OptionOperations + [<OptionSaturating $trait>]<Rhs>, |
54 | { |
55 | type Output = <T as [<OptionSaturating $trait>]<Rhs>>::Output; |
56 | |
57 | fn [<opt_saturating_ $op>](self, rhs: Rhs) -> Option<Self::Output> { |
58 | self.and_then(|inner_self| inner_self.[<opt_saturating_ $op>](rhs)) |
59 | } |
60 | } |
61 | |
62 | impl<T, InnerRhs> [<OptionSaturating $trait>]<Option<InnerRhs>, InnerRhs> for Option<T> |
63 | where |
64 | T: OptionOperations + [<OptionSaturating $trait>]<InnerRhs>, |
65 | { |
66 | type Output = <T as [<OptionSaturating $trait>]<InnerRhs>>::Output; |
67 | |
68 | fn [<opt_saturating_ $op>](self, rhs: Option<InnerRhs>) -> Option<Self::Output> { |
69 | self.zip(rhs) |
70 | .and_then(|(inner_self, inner_rhs)| inner_self.[<opt_saturating_ $op>](inner_rhs)) |
71 | } |
72 | } |
73 | |
74 | impl<T, InnerRhs> [<OptionSaturating $trait>]<&Option<InnerRhs>, InnerRhs> for Option<T> |
75 | where |
76 | T: OptionOperations + [<OptionSaturating $trait>]<InnerRhs>, |
77 | InnerRhs: Copy, |
78 | { |
79 | type Output = <T as [<OptionSaturating $trait>]<InnerRhs>>::Output; |
80 | |
81 | fn [<opt_saturating_ $op>](self, rhs: &Option<InnerRhs>) -> Option<Self::Output> { |
82 | self.zip(rhs.as_ref()) |
83 | .and_then(|(inner_self, inner_rhs)| inner_self.[<opt_saturating_ $op>](*inner_rhs)) |
84 | } |
85 | } |
86 | } |
87 | }; |
88 | } |
89 | |