1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
use std::hash::{Hash, Hasher};
use std::marker::PhantomData;
use std::path::Path;
use super::hash;
#[derive(Serialize, Deserialize, Debug, Eq)]
pub struct HashValue<T>(u64, PhantomData<T>)
where
T: Hash + ?Sized;
impl<T> HashValue<T>
where
T: Hash + ?Sized,
{
pub fn zero() -> Self {
HashValue(0, PhantomData)
}
}
impl<T> Clone for HashValue<T>
where
T: Hash + ?Sized,
{
fn clone(&self) -> Self {
HashValue(self.0, self.1)
}
}
impl<T> Copy for HashValue<T> where T: Hash + ?Sized {}
impl<T> PartialEq for HashValue<T>
where
T: Hash + ?Sized,
{
fn eq(&self, other: &Self) -> bool {
self.0.eq(&other.0)
}
}
impl<T> Hash for HashValue<T>
where
T: Hash + ?Sized,
{
fn hash<H>(&self, state: &mut H)
where
H: Hasher,
{
self.0.hash(state);
}
}
impl<F> From<F> for HashValue<str>
where
F: AsRef<str>,
{
fn from(v: F) -> Self {
HashValue(hash::hash64(v.as_ref()), PhantomData)
}
}
impl<T> From<T> for HashValue<Path>
where
T: AsRef<Path>,
{
fn from(v: T) -> Self {
HashValue(hash::hash64(v.as_ref()), PhantomData)
}
}
impl<T> PartialEq<T> for HashValue<str>
where
T: AsRef<str>,
{
fn eq(&self, other: &T) -> bool {
self.0.eq(&hash::hash64(other.as_ref()))
}
}
impl<T> PartialEq<T> for HashValue<Path>
where
T: AsRef<Path>,
{
fn eq(&self, other: &T) -> bool {
self.0.eq(&hash::hash64(other.as_ref()))
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::utils::hash::FastHashSet;
#[test]
fn hash_str() {
let hash = HashValue::<str>::from("hash_str");
assert_eq!(hash, "hash_str");
assert!(hash != "other_str");
}
#[test]
fn collections() {
let mut set = FastHashSet::<HashValue<str>>::default();
set.insert(HashValue::from("asdasd"));
set.insert(HashValue::from("asdasd"));
set.insert(HashValue::from("asdasd"));
set.insert(HashValue::from("asdasd"));
assert_eq!(set.len(), 1);
assert_eq!(
set.get(&("asdasd".into())),
Some(&HashValue::from("asdasd"))
);
}
#[test]
fn hash_path() {
let _ = HashValue::<Path>::from("str_path");
}
}