1//! Trait for the equality [`OptionOperations`].
2
3use crate::OptionOperations;
4
5/// Trait for the equality [`OptionOperations`].
6pub 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
24impl<T, Rhs> OptionEq<&Rhs, Rhs> for T
25where
26 T: OptionOperations + PartialEq<Rhs>,
27{
28 fn opt_eq(&self, rhs: &Rhs) -> Option<bool> {
29 Some(self.eq(rhs))
30 }
31}
32
33impl<T, Rhs> OptionEq<Rhs> for T
34where
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
42impl<T, InnerRhs> OptionEq<&Option<InnerRhs>, InnerRhs> for T
43where
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
51impl<T, InnerRhs> OptionEq<Option<InnerRhs>, InnerRhs> for T
52where
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
60impl<T, Rhs> OptionEq<&Rhs, Rhs> for Option<T>
61where
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
69impl<T, Rhs> OptionEq<Rhs> for Option<T>
70where
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
78impl<T, InnerRhs> OptionEq<&Option<InnerRhs>, InnerRhs> for Option<T>
79where
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
91impl<T, InnerRhs> OptionEq<Option<InnerRhs>, InnerRhs> for Option<T>
92where
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)]
105mod 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