Skip to main content

std_ext/
wrapper.rs

1use super::{tuple_deref, tuple_deref_mut, tuple_take};
2use std::hash::{Hash, Hasher};
3
4impl<T: ?Sized> OrdExt for T {}
5
6pub trait OrdExt {
7    #[inline]
8    fn eq_ord(self) -> EqOrdWrapper<Self>
9    where
10        Self: Sized,
11    {
12        EqOrdWrapper(self)
13    }
14
15    #[inline]
16    fn neq_ord(self) -> NeqOrdWrapper<Self>
17    where
18        Self: Sized,
19    {
20        NeqOrdWrapper(self)
21    }
22}
23
24#[derive(Clone)]
25pub struct NeqOrdWrapper<T>(T);
26
27tuple_deref!(NeqOrdWrapper<T>);
28tuple_deref_mut!(NeqOrdWrapper<T>);
29tuple_take!(NeqOrdWrapper<T>);
30
31impl<T> Eq for NeqOrdWrapper<T> {}
32
33impl<T> PartialEq<Self> for NeqOrdWrapper<T> {
34    #[inline]
35    fn eq(&self, _other: &Self) -> bool {
36        false
37    }
38}
39
40impl<T> PartialOrd<Self> for NeqOrdWrapper<T> {
41    #[allow(clippy::non_canonical_partial_ord_impl)]
42    fn partial_cmp(&self, _other: &Self) -> Option<std::cmp::Ordering> {
43        None
44    }
45}
46
47impl<T> Ord for NeqOrdWrapper<T> {
48    fn cmp(&self, _other: &Self) -> std::cmp::Ordering {
49        std::cmp::Ordering::Greater
50    }
51}
52
53#[derive(Clone)]
54pub struct EqOrdWrapper<T>(T);
55
56tuple_deref!(EqOrdWrapper<T>);
57tuple_deref_mut!(EqOrdWrapper<T>);
58tuple_take!(EqOrdWrapper<T>);
59
60impl<T> Eq for EqOrdWrapper<T> {}
61
62impl<T> PartialEq<Self> for EqOrdWrapper<T> {
63    #[inline]
64    fn eq(&self, _other: &Self) -> bool {
65        true
66    }
67}
68
69impl<T> PartialOrd<Self> for EqOrdWrapper<T> {
70    #[allow(clippy::non_canonical_partial_ord_impl)]
71    fn partial_cmp(&self, _other: &Self) -> Option<std::cmp::Ordering> {
72        Some(std::cmp::Ordering::Equal)
73    }
74}
75
76impl<T> Ord for EqOrdWrapper<T> {
77    fn cmp(&self, _other: &Self) -> std::cmp::Ordering {
78        std::cmp::Ordering::Equal
79    }
80}
81
82impl<T: ?Sized> HashExt for T {}
83
84pub trait HashExt {
85    #[inline]
86    fn hash_value(self, h: u64) -> HashWrapper<Self>
87    where
88        Self: Sized,
89    {
90        HashWrapper(self, h)
91    }
92
93    #[inline]
94    fn hash_empty(self) -> EmptyHashWrapper<Self>
95    where
96        Self: Sized,
97    {
98        EmptyHashWrapper(self)
99    }
100}
101
102pub struct HashWrapper<T>(T, u64);
103
104tuple_deref!(HashWrapper<T>);
105tuple_deref_mut!(HashWrapper<T>);
106
107impl<T> Hash for HashWrapper<T> {
108    fn hash<H: Hasher>(&self, state: &mut H) {
109        self.1.hash(state);
110    }
111}
112
113pub struct EmptyHashWrapper<T>(T);
114
115tuple_deref!(EmptyHashWrapper<T>);
116tuple_deref_mut!(EmptyHashWrapper<T>);
117
118impl<T> Hash for EmptyHashWrapper<T> {
119    fn hash<H: Hasher>(&self, _state: &mut H) {}
120}
121
122impl<T: ?Sized> OrdHashExt for T {}
123
124pub trait OrdHashExt {
125    #[inline]
126    fn neq_ord_hash(self, h: u64) -> NeqOrdHashWrapper<Self>
127    where
128        Self: Sized,
129    {
130        NeqOrdHashWrapper(self, h)
131    }
132
133    #[inline]
134    fn neq_ord_empty(self) -> NeqOrdEmptyHashWrapper<Self>
135    where
136        Self: Sized,
137    {
138        NeqOrdEmptyHashWrapper(self)
139    }
140}
141
142pub struct NeqOrdEmptyHashWrapper<T>(T);
143
144tuple_deref!(NeqOrdEmptyHashWrapper<T>);
145tuple_deref_mut!(NeqOrdEmptyHashWrapper<T>);
146
147impl<T> Eq for NeqOrdEmptyHashWrapper<T> {}
148
149impl<T> PartialEq<Self> for NeqOrdEmptyHashWrapper<T> {
150    #[inline]
151    fn eq(&self, _other: &Self) -> bool {
152        false
153    }
154}
155
156impl<T> PartialOrd<Self> for NeqOrdEmptyHashWrapper<T> {
157    #[allow(clippy::non_canonical_partial_ord_impl)]
158    fn partial_cmp(&self, _other: &Self) -> Option<std::cmp::Ordering> {
159        None
160    }
161}
162
163impl<T> Ord for NeqOrdEmptyHashWrapper<T> {
164    fn cmp(&self, _other: &Self) -> std::cmp::Ordering {
165        std::cmp::Ordering::Greater
166    }
167}
168
169impl<T> Hash for NeqOrdEmptyHashWrapper<T> {
170    fn hash<H: Hasher>(&self, _state: &mut H) {}
171}
172
173pub struct NeqOrdHashWrapper<T>(T, u64);
174
175tuple_deref!(NeqOrdHashWrapper<T>);
176tuple_deref_mut!(NeqOrdHashWrapper<T>);
177
178impl<T> Eq for NeqOrdHashWrapper<T> {}
179
180impl<T> PartialEq<Self> for NeqOrdHashWrapper<T> {
181    #[inline]
182    fn eq(&self, _other: &Self) -> bool {
183        false
184    }
185}
186
187impl<T> PartialOrd<Self> for NeqOrdHashWrapper<T> {
188    fn partial_cmp(&self, _other: &Self) -> Option<std::cmp::Ordering> {
189        None
190    }
191}
192
193impl<T> Hash for NeqOrdHashWrapper<T> {
194    fn hash<H: Hasher>(&self, state: &mut H) {
195        self.1.hash(state)
196    }
197}
198
199#[test]
200fn test_neq() {
201    let a1 = NeqOrdWrapper(1);
202    let a2 = NeqOrdWrapper(1);
203    assert!(a1.ne(&a2));
204}
205
206#[test]
207fn test_eq() {
208    let a1 = EqOrdWrapper(1);
209    let a2 = EqOrdWrapper(1);
210    assert!(a1.eq(&a2));
211}
212
213#[test]
214fn test_neq_ord_cmp_order() {
215    // NeqOrdWrapper always returns Greater on cmp
216    let a = NeqOrdWrapper(5);
217    let b = NeqOrdWrapper(10);
218    assert!(a.cmp(&b) == std::cmp::Ordering::Greater);
219    // PartialCmp always returns None
220    assert!(a.partial_cmp(&b).is_none());
221    // PartialEq always returns false
222    assert!(a.ne(&b));
223}
224
225#[test]
226fn test_neq_ord_clone() {
227    let a = NeqOrdWrapper("hello");
228    let b = a.clone();
229    assert_eq!(*a, "hello");
230    assert_eq!(*b, "hello");
231}
232
233#[test]
234fn test_neq_ord_deref_mut() {
235    let mut a = NeqOrdWrapper(0);
236    *a = 100;
237    assert_eq!(*a, 100);
238}
239
240#[test]
241fn test_neq_ord_take() {
242    let a = NeqOrdWrapper(42);
243    assert_eq!(a.take(), 42);
244}
245
246#[test]
247fn test_eq_ord_cmp_order() {
248    // EqOrdWrapper always returns Equal on cmp and partial_cmp
249    let a = EqOrdWrapper(5);
250    let b = EqOrdWrapper(10);
251    assert!(a.cmp(&b) == std::cmp::Ordering::Equal);
252    assert!(a.partial_cmp(&b) == Some(std::cmp::Ordering::Equal));
253    // PartialEq always returns true
254    assert!(a.eq(&b));
255}
256
257#[test]
258fn test_eq_ord_clone() {
259    let a = EqOrdWrapper(42);
260    let b = a.clone();
261    assert_eq!(*a, 42);
262    assert_eq!(*b, 42);
263}
264
265#[test]
266fn test_eq_ord_take() {
267    let a = EqOrdWrapper(99);
268    assert_eq!(a.take(), 99);
269}
270
271#[test]
272fn test_hash_wrapper_trait() {
273    use std::collections::hash_map::DefaultHasher;
274    use std::hash::{Hash, Hasher};
275
276    let mut w = HashWrapper(42, 12345);
277    assert_eq!(*w, 42);
278    *w = 100;
279    assert_eq!(*w, 100);
280
281    // Hash with same value produces same result
282    let w1 = HashWrapper("a", 999);
283    let w2 = HashWrapper("b", 999);
284
285    let mut h1 = DefaultHasher::new();
286    w1.hash(&mut h1);
287    let mut h2 = DefaultHasher::new();
288    w2.hash(&mut h2);
289    assert_eq!(h1.finish(), h2.finish());
290}
291
292#[test]
293fn test_empty_hash_wrapper_trait() {
294    use std::collections::hash_map::DefaultHasher;
295    use std::hash::{Hash, Hasher};
296
297    let w = EmptyHashWrapper(42);
298    assert_eq!(*w, 42);
299
300    let mut h = DefaultHasher::new();
301    w.hash(&mut h);
302    let default_hash = DefaultHasher::new().finish();
303    assert_eq!(h.finish(), default_hash);
304}
305
306#[test]
307fn test_neq_ord_hash_wrapper() {
308    use std::collections::hash_map::DefaultHasher;
309    use std::hash::{Hash, Hasher};
310
311    let a = NeqOrdHashWrapper(1, 100);
312    let b = NeqOrdHashWrapper(1, 100);
313
314    // PartialEq always false
315    assert!(a.ne(&b));
316
317    // Hash considers the u64 value
318    let mut h1 = DefaultHasher::new();
319    a.hash(&mut h1);
320    let mut h2 = DefaultHasher::new();
321    b.hash(&mut h2);
322    assert_eq!(h1.finish(), h2.finish());
323}
324
325#[test]
326fn test_neq_ord_empty_hash_wrapper() {
327    use std::collections::hash_map::DefaultHasher;
328    use std::hash::{Hash, Hasher};
329
330    let a = NeqOrdEmptyHashWrapper(1);
331    let b = NeqOrdEmptyHashWrapper(2);
332
333    // PartialEq always false
334    assert!(a.ne(&b));
335
336    // Ord always Greater
337    assert!(a.cmp(&b) == std::cmp::Ordering::Greater);
338
339    // Hash is empty
340    let mut h1 = DefaultHasher::new();
341    a.hash(&mut h1);
342    let mut h2 = DefaultHasher::new();
343    b.hash(&mut h2);
344    let default_hash = DefaultHasher::new().finish();
345    assert_eq!(h1.finish(), default_hash);
346    assert_eq!(h2.finish(), default_hash);
347}
348
349#[test]
350fn test_hash_ext_hash_value() {
351    let w = 42.hash_value(12345);
352    assert_eq!(*w, 42);
353}
354
355#[test]
356fn test_hash_ext_hash_empty() {
357    let w = 42.hash_empty();
358    assert_eq!(*w, 42);
359}
360
361#[test]
362fn test_ord_hash_ext_neq_ord_hash_trait() {
363    let a = "test".neq_ord_hash(777);
364    assert_eq!(*a, "test");
365}
366
367#[test]
368fn test_ord_hash_ext_neq_ord_empty_trait() {
369    let a = "test".neq_ord_empty();
370    assert_eq!(*a, "test");
371}