1use std::any::{Any, TypeId};
2use std::collections::hash_map::DefaultHasher;
3use std::hash::{Hash, Hasher};
4
5pub trait ValueKey: Send + Sync + 'static {
7 fn equals(&self, other: &dyn ValueKey) -> bool;
8 fn hash_dyn(&self, state: &mut dyn Hasher);
9 fn type_id(&self) -> TypeId;
10 fn as_any(&self) -> &dyn Any;
11}
12
13impl<T> ValueKey for T
14where
15 T: Eq + Hash + Send + Sync + 'static,
16{
17 fn equals(&self, other: &dyn ValueKey) -> bool {
18 if Any::type_id(self) != other.type_id() {
19 return false;
20 }
21 other
22 .as_any()
23 .downcast_ref::<T>()
24 .map(|v| v == self)
25 .unwrap_or(false)
26 }
27
28 fn hash_dyn(&self, state: &mut dyn Hasher) {
29 let mut tid_hasher = DefaultHasher::new();
30 TypeId::of::<T>().hash(&mut tid_hasher);
31 let mut val_hasher = DefaultHasher::new();
32 Hash::hash(self, &mut val_hasher);
33 state.write_u64(tid_hasher.finish());
34 state.write_u64(val_hasher.finish());
35 }
36
37 fn type_id(&self) -> TypeId {
38 TypeId::of::<T>()
39 }
40
41 fn as_any(&self) -> &dyn Any {
42 self
43 }
44}