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