1use std::borrow::Borrow;
2use std::collections::hash_map::DefaultHasher;
3use std::hash::{Hash, Hasher};
4use std::marker::PhantomData;
5
6#[derive(Debug)]
7pub struct HashOf<T, H: Hasher = DefaultHasher> {
8 hash: u64,
9 _marker: PhantomData<*const (T, H)>, }
11
12impl<T, H: Hasher> PartialEq for HashOf<T, H> {
15 #[inline]
16 fn eq(&self, other: &Self) -> bool {
17 self.hash == other.hash
18 }
19}
20
21impl<T, H: Hasher> Eq for HashOf<T, H> {}
22
23impl<T, H: Hasher> Hash for HashOf<T, H> {
24 #[inline]
25 fn hash<H2: Hasher>(&self, state: &mut H2) {
26 state.write_u64(self.hash)
27 }
28}
29
30impl<T> Clone for HashOf<T> {
31 #[inline]
32 fn clone(&self) -> Self {
33 *self
34 }
35}
36
37impl<T> Copy for HashOf<T> {}
38
39impl<T> HashOf<T> {
40 #[inline]
41 pub fn to_inner(self) -> u64 {
42 self.hash
43 }
44}
45
46impl<T: Hash + ?Sized, Q: Borrow<T>, H: Hasher + Default> From<&T> for HashOf<Q, H> {
50 fn from(value: &T) -> Self {
51 let mut hasher = H::default();
52 value.hash(&mut hasher);
53 Self {
54 hash: hasher.finish(),
55 _marker: PhantomData,
56 }
57 }
58}
59
60#[cfg(test)]
61mod tests {
62 use super::*;
63
64 #[test]
65 fn borrow_hash_eq() {
66 let x = HashOf::<String>::from("test");
67 let s2 = String::new() + "test";
68 let y = HashOf::from(&s2);
69 assert_eq!(x, y);
70 }
71
72 #[test]
73 fn can_hash_non_borrow() {
74 let x = HashOf::<u32>::from(&0);
76 assert_ne!(x.to_inner(), 0);
77 }
78}