option_operations/macros/
option_op.rs

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}