option_operations/
eq.rs

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| !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| 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| 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| 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), Some(inner_rhs)) => 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), Some(inner_rhs)) => 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}