lang_extension/any/
key.rs1use std::collections::hash_map::DefaultHasher;
2use std::hash::{Hash, Hasher};
3
4use super::*;
5
6pub trait KeyConstraint: ValueConstraint + Eq + Hash {}
7
8impl<T: ?Sized + ValueConstraint + Eq + Hash> KeyConstraint for T {}
9
10pub trait Key: Value {
11 fn hashcode(&self) -> u64 {
12 self.memory_address() as u64
13 }
14
15 as_trait!(Key);
16 as_boxed!(Key);
17}
18
19impl<T: ?Sized + KeyConstraint> Key for T {
20 fn hashcode(&self) -> u64 {
21 let mut hasher = DefaultHasher::default();
22 self.hash(&mut hasher);
23 hasher.finish()
24 }
25
26 as_trait!(impl Key);
27 as_boxed!(impl Key);
28}
29
30#[macro_export]
31macro_rules! boxed_key_trait {
32 ($trait:tt) => {
33as_boxed!(impl Eq for $trait);
34as_boxed!(impl Hash for $trait);
35boxed_value_trait!($trait);
36 };
37
38 ($trait:tt<$($param:tt), *>) => {
39as_boxed!(impl Eq for $trait<$($param), *>);
40as_boxed!(impl Hash for $trait<$($param), *>);
41boxed_value_trait!($trait<$($param), *>);
42 };
43
44 ($trait:tt<$($param:tt: $constraint0:tt $(+ $constraint:tt)*), *>) => {
45as_boxed!(impl Eq for $trait<$($param: $constraint0 $(+ $constraint)*), *>);
46as_boxed!(impl Hash for $trait<$($param: $constraint0 $(+ $constraint)*), *>);
47boxed_value_trait!($trait<$($param: $constraint0 $(+ $constraint)*), *>);
48 };
49
50 ($trait:tt<$($param:tt: ?Sized + $constraint0:tt $(+ $constraint:tt)*), *>) => {
51as_boxed!(impl Eq for $trait<$($param: ?Sized + $constraint0 $(+ $constraint)*), *>);
52as_boxed!(impl Hash for $trait<$($param: ?Sized + $constraint0 $(+ $constraint)*), *>);
53boxed_value_trait!($trait<$($param: ?Sized + $constraint0 $(+ $constraint)*), *>);
54 };
55
56 ($trait:tt<$($param:tt: 'static + $constraint0:tt $(+ $constraint:tt)*), *>) => {
57as_boxed!(impl Eq for $trait<$($param: 'static + $constraint0 $(+ $constraint)*), *>);
58as_boxed!(impl Hash for $trait<$($param: 'static + $constraint0 $(+ $constraint)*), *>);
59boxed_value_trait!($trait<$($param: 'static + $constraint0 $(+ $constraint)*), *>);
60 };
61
62 ($trait:tt<$($param:tt: 'static + ?Sized + $constraint0:tt $(+ $constraint:tt)*), *>) => {
63as_boxed!(impl Eq for $trait<$($param: 'static + ?Sized + $constraint0 $(+ $constraint)*), *>);
64as_boxed!(impl Hash for $trait<$($param: 'static + ?Sized + $constraint0 $(+ $constraint)*), *>);
65boxed_value_trait!($trait<$($param: 'static + ?Sized + $constraint0 $(+ $constraint)*), *>);
66 };
67}
68
69boxed_key_trait!(Key);
70
71#[allow(dead_code)]
72#[cfg(test)]
73mod tests {
74
75 use super::*;
76 use crate::*;
77 use std::collections::HashMap;
78 use std::fmt::Debug;
79
80 trait K1<K: KeyConstraint>: Key {
81 fn say(&self, _k: K) {}
82
83 as_boxed!(K1<K>);
84 }
85
86 #[derive(Hash, PartialEq, Eq, Debug, Clone)]
87 struct S1 {
88 a: i32,
89 b: u32,
90 }
91
92 impl<K: KeyConstraint> K1<K> for S1 {
93 as_boxed!(impl K1<K>);
94 }
95
96 boxed_key_trait!(K1<K: KeyConstraint>);
97
98 #[test]
99 fn hashcode() {
100 let s = S1 { a: 1, b: 2 };
101 assert_eq!(s.hashcode(), s.clone().hashcode());
102
103 let bs: Box<dyn Key> = Box::new(s);
104 assert_eq!(bs.hashcode(), bs.clone().hashcode());
105
106 let mut hasher = DefaultHasher::new();
107 bs.hash(&mut hasher);
108 let _ = hasher.finish();
109 }
110
111 #[test]
112 fn hashmap() {
113 let k = S1 { a: 1, b: 2 };
114 let v = S1 { a: 11, b: 22 };
115 let key: Box<dyn Key> = Box::new(k.clone());
116 let value: Box<dyn Value> = Box::new(v.clone());
117 let mut map = HashMap::<Box<dyn Key>, Box<dyn Value>>::new();
118 map.insert(key.clone(), value.clone());
119 assert_eq!(&value, map.get(&key).unwrap());
120 }
121
122 trait SomeType0<K: KeyConstraint, V: ValueConstraint>: Key {
123 fn say(&self, k: K, v: V);
124
125 as_boxed!(SomeType0<K, V>);
126 as_trait!(SomeType0<K, V>);
127 }
128
129 boxed_key_trait!(SomeType0<K: KeyConstraint, V: ValueConstraint>);
130
131 trait SomeType1<K: KeyConstraint + Debug, V: ValueConstraint>: Key {
132 fn say(&self, k: K, v: V);
133
134 as_boxed!(SomeType1<K, V>);
135 as_trait!(SomeType1<K, V>);
136 }
137
138 boxed_key_trait!(SomeType1<K: KeyConstraint + Debug, V: ValueConstraint>);
139
140 trait SomeType2<K: ?Sized + KeyConstraint, V: ?Sized + ValueConstraint>: Key {
141 fn say(&self, k: K, v: V);
142
143 as_boxed!(SomeType2<K, V>);
144 as_trait!(SomeType2<K, V>);
145 }
146
147 boxed_key_trait!(SomeType2<K: ?Sized + KeyConstraint, V: ?Sized + ValueConstraint>);
148
149 trait SomeType3<K: 'static + KeyConstraint, V: 'static + ValueConstraint>: Key {
150 fn say(&self, k: K, v: V);
151
152 as_boxed!(SomeType3<K, V>);
153 as_trait!(SomeType3<K, V>);
154 }
155
156 boxed_key_trait!(SomeType3<K: 'static + KeyConstraint, V: 'static + ValueConstraint>);
157
158 trait SomeType4<K: 'static + ?Sized + KeyConstraint, V: 'static + ?Sized + ValueConstraint>:
159 Key
160 {
161 fn say(&self, k: K, v: V);
162
163 as_boxed!(SomeType4<K, V>);
164 as_trait!(SomeType4<K, V>);
165 }
166
167 boxed_key_trait!(SomeType4<K: 'static + ?Sized + KeyConstraint, V: 'static + ?Sized + ValueConstraint>);
168}