1use core::cmp::Ordering;
2use core::hash::{Hash, Hasher};
3
4pub trait RefKey {
6 type Output;
8
9 fn key(&self) -> &Self::Output;
11}
12
13#[derive(Clone, Copy, Debug, Default)]
15pub struct RefKeyed<T>(pub T);
16
17impl<T> From<T> for RefKeyed<T> {
18 fn from(value: T) -> Self {
19 Self(value)
20 }
21}
22
23impl<T: RefKey> PartialEq for RefKeyed<T>
24where
25 T::Output: PartialEq,
26{
27 fn eq(&self, other: &Self) -> bool {
28 self.0.key().eq(other.0.key())
29 }
30
31 #[allow(clippy::partialeq_ne_impl)]
32 fn ne(&self, other: &Self) -> bool {
33 self.0.key().ne(other.0.key())
34 }
35}
36
37impl<T: RefKey> Eq for RefKeyed<T> where T::Output: Eq {}
38
39impl<T: RefKey> PartialOrd for RefKeyed<T>
40where
41 T::Output: PartialOrd,
42{
43 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
44 self.0.key().partial_cmp(other.0.key())
45 }
46
47 fn lt(&self, other: &Self) -> bool {
48 self.0.key().lt(other.0.key())
49 }
50
51 fn le(&self, other: &Self) -> bool {
52 self.0.key().le(other.0.key())
53 }
54
55 fn gt(&self, other: &Self) -> bool {
56 self.0.key().gt(other.0.key())
57 }
58
59 fn ge(&self, other: &Self) -> bool {
60 self.0.key().ge(other.0.key())
61 }
62}
63
64impl<T: RefKey> Ord for RefKeyed<T>
65where
66 T::Output: Ord,
67{
68 fn cmp(&self, other: &Self) -> Ordering {
69 self.0.key().cmp(other.0.key())
70 }
71}
72
73impl<T: RefKey> Hash for RefKeyed<T>
74where
75 T::Output: Hash,
76{
77 fn hash<H: Hasher>(&self, state: &mut H) {
78 self.0.key().hash(state)
79 }
80}
81
82#[cfg(test)]
83mod tests {
84 use super::super::tests::{self, KeyValuePair};
85 use super::{RefKey, RefKeyed};
86
87 impl<K, V> RefKey for KeyValuePair<K, V> {
88 type Output = K;
89
90 fn key(&self) -> &Self::Output {
91 &self.key
92 }
93 }
94
95 #[test]
96 fn test_partial_eq() {
97 tests::test_partial_eq(RefKeyed);
98 }
99
100 #[test]
101 fn test_eq() {
102 tests::test_eq(RefKeyed);
103 }
104
105 #[test]
106 fn test_partial_ord() {
107 tests::test_partial_ord(RefKeyed);
108 }
109
110 #[test]
111 fn test_ord() {
112 tests::test_ord(RefKeyed);
113 }
114
115 #[test]
116 fn test_hash() {
117 tests::test_hash(RefKeyed);
118 }
119}