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}
91