1macro_rules! option_op {
2 ($op_trait:ident, $op:ident, $op_name:ident $(, $extra_doc:expr)? $(,)?) => {
3 paste::paste! {
4 #[doc = "Trait for values and `Option`s " $op_name "."]
5 ///
6 /// Implementing this trait leads to the following auto-implementations:
7 ///
8 #[doc = "- `" [<Option $op_trait>] "<Option<InnerRhs>>` for `T`."]
9 #[doc = "- `" [<Option $op_trait>] "<Rhs>` for `Option<T>`."]
10 #[doc = "- `" [<Option $op_trait>] "<Option<InnerRhs>>` for `Option<T>`."]
11 /// - ... and some variants with references.
12 ///
13 /// This trait is auto-implemented for [`OptionOperations`] types implementing
14 #[doc = "`" $op_trait "<Rhs>`."]
15 pub trait [<Option $op_trait>]<Rhs= Self, InnerRhs = Rhs> {
16 #[doc = "The resulting inner type after applying the " $op_name "."]
17 type Output;
18
19 #[doc = "Computes the " $op_name "."]
20 ///
21 /// Returns `None` if at least one argument is `None`.
22 $(#[doc = $extra_doc])?
23 #[must_use]
24 fn [<opt_ $op>](self, rhs: Rhs) -> Option<Self::Output>;
25 }
26
27 impl<T, Rhs> [<Option $op_trait>]<Rhs> for T
28 where
29 T: OptionOperations + $op_trait<Rhs>,
30 {
31 type Output = <T as $op_trait<Rhs>>::Output;
32
33 fn [<opt_ $op>](self, rhs: Rhs) -> Option<Self::Output> {
34 Some(self.$op(rhs))
35 }
36 }
37
38 impl<T, InnerRhs> [<Option $op_trait>]<Option<InnerRhs>, InnerRhs> for T
39 where
40 T: OptionOperations + [<Option $op_trait>]<InnerRhs>,
41 {
42 type Output = <T as [<Option $op_trait>]<InnerRhs>>::Output;
43
44 fn [<opt_ $op>](self, rhs: Option<InnerRhs>) -> Option<Self::Output> {
45 rhs.and_then(|inner_rhs| self.[<opt_ $op>](inner_rhs))
46 }
47 }
48
49 impl<T, InnerRhs> [<Option $op_trait>]<&Option<InnerRhs>, InnerRhs> for T
50 where
51 T: OptionOperations + [<Option $op_trait>]<InnerRhs>,
52 InnerRhs: Copy,
53 {
54 type Output = <T as [<Option $op_trait>]<InnerRhs>>::Output;
55
56 fn [<opt_ $op>](self, rhs: &Option<InnerRhs>) -> Option<Self::Output> {
57 rhs.as_ref().and_then(|inner_rhs| self.[<opt_ $op>](*inner_rhs))
58 }
59 }
60
61 impl<T, Rhs> [<Option $op_trait>]<Rhs> for Option<T>
62 where
63 T: OptionOperations + [<Option $op_trait>]<Rhs>,
64 {
65 type Output = <T as [<Option $op_trait>]<Rhs>>::Output;
66
67 fn [<opt_ $op>](self, rhs: Rhs) -> Option<Self::Output> {
68 self.and_then(|inner_self| inner_self.[<opt_ $op>](rhs))
69 }
70 }
71
72 impl<T, InnerRhs> [<Option $op_trait>]<Option<InnerRhs>, InnerRhs> for Option<T>
73 where
74 T: OptionOperations + [<Option $op_trait>]<InnerRhs>,
75 {
76 type Output = <T as [<Option $op_trait>]<InnerRhs>>::Output;
77
78 fn [<opt_ $op>](self, rhs: Option<InnerRhs>) -> Option<Self::Output> {
79 self.zip(rhs)
80 .and_then(|(inner_self, inner_rhs)| inner_self.[<opt_ $op>](inner_rhs))
81 }
82 }
83
84 impl<T, InnerRhs> [<Option $op_trait>]<&Option<InnerRhs>, InnerRhs> for Option<T>
85 where
86 T: OptionOperations + [<Option $op_trait>]<InnerRhs>,
87 InnerRhs: Copy,
88 {
89 type Output = <T as [<Option $op_trait>]<InnerRhs>>::Output;
90
91 fn [<opt_ $op>](self, rhs: &Option<InnerRhs>) -> Option<Self::Output> {
92 self.zip(rhs.as_ref())
93 .and_then(|(inner_self, inner_rhs)| inner_self.[<opt_ $op>](*inner_rhs))
94 }
95 }
96 }
97 };
98}
99