option_operations/macros/
option_op_checked.rs

1macro_rules! option_op_checked {
2    ($trait:ident, $op:ident, $op_name:ident $(, $extra_doc:expr)? $(,)?) => {
3        pastey::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}