1 | macro_rules! option_op_checked { |
2 | ($trait:ident, $op:ident, $op_name:ident $(, $extra_doc:expr)? $(,)?) => { |
3 | paste::paste! { |
4 | #[doc = "Trait for values and `Option`s checked " $op_name "." ] |
5 | /// |
6 | /// Implementing this trait leads to the following auto-implementations: |
7 | /// |
8 | #[doc = "- `" [<OptionChecked $trait>] "<Option<InnerRhs>>` for `T`." ] |
9 | #[doc = "- `" [<OptionChecked $trait>] "<Rhs>` for `Option<T>`." ] |
10 | #[doc = "- `" [<OptionChecked $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 = "`" [<Checked $trait >] "` trait, " ] |
15 | /// users must provide the base implementation for the inner type. |
16 | pub trait [<OptionChecked $trait>]<Rhs = Self, InnerRhs = Rhs> { |
17 | #[doc = "The resulting inner type after applying the " $op_name "." ] |
18 | type Output; |
19 | |
20 | #[doc = "Computes the checked " $op_name "." ] |
21 | /// |
22 | /// - Returns `Ok(Some(result))` if `result` could be computed. |
23 | /// - Returns `Ok(None)` if at least one argument is `None`. |
24 | /// - Returns `Err(Error::Overflow)` if an overflow occured. |
25 | $(#[doc = $extra_doc])? |
26 | fn [<opt_checked_ $op>](self, rhs: Rhs) -> Result<Option<Self::Output>, Error>; |
27 | } |
28 | |
29 | impl<T, InnerRhs> [<OptionChecked $trait>]<Option<InnerRhs>, InnerRhs> for T |
30 | where |
31 | T: OptionOperations + [<OptionChecked $trait>]<InnerRhs>, |
32 | { |
33 | type Output = <T as [<OptionChecked $trait>]<InnerRhs>>::Output; |
34 | |
35 | fn [<opt_checked_ $op>](self, rhs: Option<InnerRhs>) -> Result<Option<Self::Output>, Error> { |
36 | if let Some(inner_rhs) = rhs { |
37 | self.[<opt_checked_ $op>](inner_rhs) |
38 | } else { |
39 | Ok(None) |
40 | } |
41 | } |
42 | } |
43 | |
44 | impl<T, InnerRhs> [<OptionChecked $trait>]<&Option<InnerRhs>, InnerRhs> for T |
45 | where |
46 | T: OptionOperations + [<OptionChecked $trait>]<InnerRhs>, |
47 | InnerRhs: Copy, |
48 | { |
49 | type Output = <T as [<OptionChecked $trait>]<InnerRhs>>::Output; |
50 | |
51 | fn [<opt_checked_ $op>](self, rhs: &Option<InnerRhs>) -> Result<Option<Self::Output>, Error> { |
52 | if let Some(inner_rhs) = rhs.as_ref() { |
53 | self.[<opt_checked_ $op>](*inner_rhs) |
54 | } else { |
55 | Ok(None) |
56 | } |
57 | } |
58 | } |
59 | |
60 | impl<T, Rhs> [<OptionChecked $trait>]<Rhs> for Option<T> |
61 | where |
62 | T: OptionOperations + [<OptionChecked $trait>]<Rhs>, |
63 | { |
64 | type Output = <T as [<OptionChecked $trait>]<Rhs>>::Output; |
65 | |
66 | fn [<opt_checked_ $op>](self, rhs: Rhs) -> Result<Option<Self::Output>, Error> { |
67 | if let Some(inner_self) = self { |
68 | inner_self.[<opt_checked_ $op>](rhs) |
69 | } else { |
70 | Ok(None) |
71 | } |
72 | } |
73 | } |
74 | |
75 | impl<T, InnerRhs> [<OptionChecked $trait>]<Option<InnerRhs>, InnerRhs> for Option<T> |
76 | where |
77 | T: OptionOperations + [<OptionChecked $trait>]<InnerRhs>, |
78 | { |
79 | type Output = <T as [<OptionChecked $trait>]<InnerRhs>>::Output; |
80 | |
81 | fn [<opt_checked_ $op>](self, rhs: Option<InnerRhs>) -> Result<Option<Self::Output>, Error> { |
82 | if let (Some(inner_self), Some(inner_rhs)) = (self, rhs) { |
83 | inner_self.[<opt_checked_ $op>](inner_rhs) |
84 | } else { |
85 | Ok(None) |
86 | } |
87 | } |
88 | } |
89 | |
90 | impl<T, InnerRhs> [<OptionChecked $trait>]<&Option<InnerRhs>, InnerRhs> for Option<T> |
91 | where |
92 | T: OptionOperations + [<OptionChecked $trait>]<InnerRhs>, |
93 | InnerRhs: Copy, |
94 | { |
95 | type Output = <T as [<OptionChecked $trait>]<InnerRhs>>::Output; |
96 | |
97 | fn [<opt_checked_ $op>](self, rhs: &Option<InnerRhs>) -> Result<Option<Self::Output>, Error> { |
98 | if let (Some(inner_self), Some(inner_rhs)) = (self, rhs.as_ref()) { |
99 | inner_self.[<opt_checked_ $op>](*inner_rhs) |
100 | } else { |
101 | Ok(None) |
102 | } |
103 | } |
104 | } |
105 | } |
106 | }; |
107 | } |
108 | |