| 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> dynOptionEq<&'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> dynOptionEq<&'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> dynOptionEq<&'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> dynOptionEq<&'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> dynOptionEq<&'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> dynOptionEq<&'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> dynOptionEq<&'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 | |