option_operations/macros/
option_op_overflowing.rs

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