1 | //! Trait for the equality [`OptionOperations`]. |
2 | |
3 | use crate::OptionOperations; |
4 | |
5 | /// Trait for the equality [`OptionOperations`]. |
6 | pub trait OptionEq<Rhs, InnerRhs = Rhs> { |
7 | /// Tests whether `self` is equal to `other`. |
8 | /// |
9 | /// Returns `None` if they can't be compared, e.g. if |
10 | /// at most one argument is `None`. |
11 | #[must_use ] |
12 | fn opt_eq(&self, other: Rhs) -> Option<bool>; |
13 | |
14 | /// Tests whether `self` is not equal to `other`. |
15 | /// |
16 | /// Returns `None` if they can't be compared, e.g. if |
17 | /// at most one argument is `None`. |
18 | #[must_use ] |
19 | fn opt_ne(&self, other: Rhs) -> Option<bool> { |
20 | self.opt_eq(other).map(|res: bool| !res) |
21 | } |
22 | } |
23 | |
24 | impl<T, Rhs> OptionEq<&Rhs, Rhs> for T |
25 | where |
26 | T: OptionOperations + PartialEq<Rhs>, |
27 | { |
28 | fn opt_eq(&self, rhs: &Rhs) -> Option<bool> { |
29 | Some(self.eq(rhs)) |
30 | } |
31 | } |
32 | |
33 | impl<T, Rhs> OptionEq<Rhs> for T |
34 | where |
35 | T: OptionOperations + for<'a> OptionEq<&'a Rhs, Rhs>, |
36 | { |
37 | fn opt_eq(&self, rhs: Rhs) -> Option<bool> { |
38 | self.opt_eq(&rhs) |
39 | } |
40 | } |
41 | |
42 | impl<T, InnerRhs> OptionEq<&Option<InnerRhs>, InnerRhs> for T |
43 | where |
44 | T: OptionOperations + for<'a> OptionEq<&'a InnerRhs, InnerRhs>, |
45 | { |
46 | fn opt_eq(&self, rhs: &Option<InnerRhs>) -> Option<bool> { |
47 | rhs.as_ref().and_then(|inner_rhs: &InnerRhs| self.opt_eq(inner_rhs)) |
48 | } |
49 | } |
50 | |
51 | impl<T, InnerRhs> OptionEq<Option<InnerRhs>, InnerRhs> for T |
52 | where |
53 | T: OptionOperations + for<'a> OptionEq<&'a InnerRhs, InnerRhs>, |
54 | { |
55 | fn opt_eq(&self, rhs: Option<InnerRhs>) -> Option<bool> { |
56 | rhs.as_ref().and_then(|inner_rhs: &InnerRhs| self.opt_eq(inner_rhs)) |
57 | } |
58 | } |
59 | |
60 | impl<T, Rhs> OptionEq<&Rhs, Rhs> for Option<T> |
61 | where |
62 | T: OptionOperations + for<'a> OptionEq<&'a Rhs, Rhs>, |
63 | { |
64 | fn opt_eq(&self, rhs: &Rhs) -> Option<bool> { |
65 | self.as_ref().and_then(|inner_self: &T| inner_self.opt_eq(rhs)) |
66 | } |
67 | } |
68 | |
69 | impl<T, Rhs> OptionEq<Rhs> for Option<T> |
70 | where |
71 | T: OptionOperations + for<'a> OptionEq<&'a Rhs, Rhs>, |
72 | { |
73 | fn opt_eq(&self, rhs: Rhs) -> Option<bool> { |
74 | self.opt_eq(&rhs) |
75 | } |
76 | } |
77 | |
78 | impl<T, InnerRhs> OptionEq<&Option<InnerRhs>, InnerRhs> for Option<T> |
79 | where |
80 | T: OptionOperations + for<'a> OptionEq<&'a InnerRhs, InnerRhs>, |
81 | { |
82 | fn opt_eq(&self, rhs: &Option<InnerRhs>) -> Option<bool> { |
83 | match (self, rhs) { |
84 | (Some(inner_self: &T), Some(inner_rhs: &InnerRhs)) => inner_self.opt_eq(inner_rhs), |
85 | (None, None) => Some(true), |
86 | _ => None, |
87 | } |
88 | } |
89 | } |
90 | |
91 | impl<T, InnerRhs> OptionEq<Option<InnerRhs>, InnerRhs> for Option<T> |
92 | where |
93 | T: OptionOperations + for<'a> OptionEq<&'a InnerRhs, InnerRhs>, |
94 | { |
95 | fn opt_eq(&self, rhs: Option<InnerRhs>) -> Option<bool> { |
96 | match (self, rhs.as_ref()) { |
97 | (Some(inner_self: &T), Some(inner_rhs: &InnerRhs)) => inner_self.opt_eq(inner_rhs), |
98 | (None, None) => Some(true), |
99 | _ => None, |
100 | } |
101 | } |
102 | } |
103 | |
104 | #[cfg (test)] |
105 | mod test { |
106 | use super::OptionEq; |
107 | use crate::OptionOperations; |
108 | |
109 | #[derive (Copy, Clone, Debug, PartialEq, PartialOrd)] |
110 | struct MyInt(u64); |
111 | |
112 | impl OptionOperations for MyInt {} |
113 | |
114 | const MY_1: MyInt = MyInt(1); |
115 | const MY_2: MyInt = MyInt(2); |
116 | const SOME_1: Option<MyInt> = Some(MY_1); |
117 | const SOME_2: Option<MyInt> = Some(MY_2); |
118 | const NONE: Option<MyInt> = None; |
119 | |
120 | #[test ] |
121 | fn opt_eq() { |
122 | assert_eq!(MY_1.opt_eq(MY_1), Some(true)); |
123 | assert_eq!(MY_1.opt_eq(SOME_1), Some(true)); |
124 | assert_eq!(SOME_1.opt_eq(MY_1), Some(true)); |
125 | assert_eq!(SOME_1.opt_eq(SOME_1), Some(true)); |
126 | |
127 | assert_eq!(MY_1.opt_eq(MY_2), Some(false)); |
128 | assert_eq!(MY_1.opt_eq(SOME_2), Some(false)); |
129 | assert_eq!(SOME_1.opt_eq(MY_2), Some(false)); |
130 | assert_eq!(SOME_1.opt_eq(SOME_2), Some(false)); |
131 | |
132 | assert_eq!(MY_1.opt_eq(NONE), None); |
133 | assert_eq!(NONE.opt_eq(SOME_2), None); |
134 | assert_eq!(SOME_1.opt_eq(NONE), None); |
135 | assert_eq!(NONE.opt_eq(SOME_2), None); |
136 | assert_eq!(NONE.opt_eq(NONE), Some(true)); |
137 | } |
138 | |
139 | #[test ] |
140 | fn opt_ne() { |
141 | assert_eq!(MY_1.opt_ne(MY_1), Some(false)); |
142 | assert_eq!(MY_1.opt_ne(SOME_1), Some(false)); |
143 | assert_eq!(SOME_1.opt_ne(MY_1), Some(false)); |
144 | assert_eq!(SOME_1.opt_ne(SOME_1), Some(false)); |
145 | |
146 | assert_eq!(MY_1.opt_ne(MY_2), Some(true)); |
147 | assert_eq!(MY_1.opt_ne(SOME_2), Some(true)); |
148 | assert_eq!(SOME_1.opt_ne(MY_2), Some(true)); |
149 | assert_eq!(SOME_1.opt_ne(SOME_2), Some(true)); |
150 | |
151 | assert_eq!(MY_1.opt_ne(NONE), None); |
152 | assert_eq!(NONE.opt_ne(SOME_2), None); |
153 | assert_eq!(SOME_1.opt_ne(NONE), None); |
154 | assert_eq!(NONE.opt_ne(SOME_2), None); |
155 | assert_eq!(NONE.opt_ne(NONE), Some(false)); |
156 | } |
157 | } |
158 | |