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