1macro_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