option_operations/macros/
option_op_wrapping.rs

1macro_rules! option_op_wrapping {
2    ($trait:ident, $op:ident, $op_name:ident $(, $extra_doc:expr)? $(,)?) => {
3        paste::paste! {
4            #[doc = "Trait for values and `Option`s wrapping " $op_name "."]
5            ///
6            /// Implementing this trait leads to the following auto-implementations:
7            ///
8            #[doc = "- `" [<OptionWrapping $trait>] "<Option<InnerRhs>>` for `T`."]
9            #[doc = "- `" [<OptionWrapping $trait>] "<Rhs>` for `Option<T>`."]
10            #[doc = "- `" [<OptionWrapping $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 = "`" [<Wrapping $trait >] "` trait, "]
15            /// users must provide the base implementation for the inner type.
16            pub trait [<OptionWrapping $trait>]<Rhs = Self, InnerRhs = Rhs> {
17                #[doc = "The resulting inner type after applying the " $op_name "."]
18                type Output;
19
20                #[doc = "Computes the " $op_name]
21                /// wrapping at the numeric bounds instead of overflowing.
22                ///
23                /// Returns `None` if at least one argument is `None`.
24                $(#[doc = $extra_doc])?
25                fn [<opt_wrapping_ $op>](self, rhs: Rhs) -> Option<Self::Output>;
26            }
27
28            impl<T, InnerRhs> [<OptionWrapping $trait>]<Option<InnerRhs>, InnerRhs> for T
29            where
30                T: OptionOperations + [<OptionWrapping $trait>]<InnerRhs>,
31            {
32                type Output = <T as [<OptionWrapping $trait>]<InnerRhs>>::Output;
33
34                fn [<opt_wrapping_ $op>](self, rhs: Option<InnerRhs>) -> Option<Self::Output> {
35                    rhs.and_then(|inner_rhs| self.[<opt_wrapping_ $op>](inner_rhs))
36                }
37            }
38
39            impl<T, InnerRhs> [<OptionWrapping $trait>]<&Option<InnerRhs>, InnerRhs> for T
40            where
41                T: OptionOperations + [<OptionWrapping $trait>]<InnerRhs>,
42                InnerRhs: Copy,
43            {
44                type Output = <T as [<OptionWrapping $trait>]<InnerRhs>>::Output;
45
46                fn [<opt_wrapping_ $op>](self, rhs: &Option<InnerRhs>) -> Option<Self::Output> {
47                    rhs.as_ref()
48                        .and_then(|inner_rhs| self.[<opt_wrapping_ $op>](*inner_rhs))
49                }
50            }
51
52            impl<T, Rhs> [<OptionWrapping $trait>]<Rhs> for Option<T>
53            where
54                T: OptionOperations + [<OptionWrapping $trait>]<Rhs>,
55            {
56                type Output = <T as [<OptionWrapping $trait>]<Rhs>>::Output;
57
58                fn [<opt_wrapping_ $op>](self, rhs: Rhs) -> Option<Self::Output> {
59                    self.and_then(|inner_self| inner_self.[<opt_wrapping_ $op>](rhs))
60                }
61            }
62
63            impl<T, InnerRhs> [<OptionWrapping $trait>]<Option<InnerRhs>, InnerRhs> for Option<T>
64            where
65                T: OptionOperations + [<OptionWrapping $trait>]<InnerRhs>,
66            {
67                type Output = <T as [<OptionWrapping $trait>]<InnerRhs>>::Output;
68
69                fn [<opt_wrapping_ $op>](self, rhs: Option<InnerRhs>) -> Option<Self::Output> {
70                    self.zip(rhs)
71                        .and_then(|(inner_self, inner_rhs)| inner_self.[<opt_wrapping_ $op>](inner_rhs))
72                }
73            }
74
75            impl<T, InnerRhs> [<OptionWrapping $trait>]<&Option<InnerRhs>, InnerRhs> for Option<T>
76            where
77                T: OptionOperations + [<OptionWrapping $trait>]<InnerRhs>,
78                InnerRhs: Copy,
79            {
80                type Output = <T as [<OptionWrapping $trait>]<InnerRhs>>::Output;
81
82                fn [<opt_wrapping_ $op>](self, rhs: &Option<InnerRhs>) -> Option<Self::Output> {
83                    self.zip(rhs.as_ref())
84                        .and_then(|(inner_self, inner_rhs)| inner_self.[<opt_wrapping_ $op>](*inner_rhs))
85                }
86            }
87        }
88    };
89}