1use std::hash::{BuildHasherDefault, Hash, Hasher};
17
18pub use indexmap::set::Iter as IndexSetIter;
19use indexmap::IndexSet as RawIndexSet;
20pub use rustc_hash::{FxHashMap as HashMap, FxHashSet as HashSet, FxHasher};
21use xxhash_rust::xxh3::Xxh3Default;
22
23type FxBuildHasher = BuildHasherDefault<FxHasher>;
24
25pub type IndexSet<T> = RawIndexSet<T, FxBuildHasher>;
26
27pub type HashValueType = u128;
28
29pub(crate) type DeterministicHasher = Xxh3Default;
30
31pub struct HasherWriter<'a, H> {
33 hasher: &'a mut H,
34 pos: usize,
35}
36
37impl<'a, H> HasherWriter<'a, H> {
38 #[must_use]
39 pub fn new(hasher: &'a mut H) -> Self {
40 Self { hasher, pos: 0 }
41 }
42}
43
44impl<H: Hasher> rkyv::ser::Positional for HasherWriter<'_, H> {
45 fn pos(&self) -> usize {
46 self.pos
47 }
48}
49
50impl<H: Hasher> rkyv::ser::Writer<rkyv::rancor::Error> for HasherWriter<'_, H> {
51 fn write(&mut self, bytes: &[u8]) -> Result<(), rkyv::rancor::Error> {
52 self.hasher.write(bytes);
53 self.pos += bytes.len();
54 Ok(())
55 }
56}
57
58#[derive(Debug, Clone, Copy)]
60pub struct EqualityBufferWriter<const N: usize> {
61 buf: [u8; N],
62 pos: usize,
63}
64
65impl<const N: usize> EqualityBufferWriter<N> {
66 #[must_use]
67 pub fn new() -> Self {
68 Self {
69 buf: [0; N],
70 pos: 0,
71 }
72 }
73
74 #[must_use]
75 pub fn as_written(&self) -> &[u8] {
76 &self.buf[..self.pos]
77 }
78}
79
80impl<const N: usize> Default for EqualityBufferWriter<N> {
81 fn default() -> Self {
82 Self::new()
83 }
84}
85
86impl<const N: usize> rkyv::ser::Positional for EqualityBufferWriter<N> {
87 fn pos(&self) -> usize {
88 self.pos
89 }
90}
91
92impl<const N: usize, E: rkyv::rancor::Source> rkyv::ser::Writer<E> for EqualityBufferWriter<N> {
93 fn write(&mut self, bytes: &[u8]) -> Result<(), E> {
94 let end = self.pos + bytes.len();
95 assert!(
96 end <= N,
97 "serialized form exceeded fixed buffer size: {} > {}",
98 end,
99 N
100 );
101 self.buf[self.pos..end].copy_from_slice(bytes);
102 self.pos = end;
103 Ok(())
104 }
105}
106
107pub trait HashMapExt {
109 #[must_use]
110 fn new() -> Self;
111}
112
113impl<K, V> HashMapExt for HashMap<K, V> {
114 fn new() -> Self {
115 HashMap::default()
116 }
117}
118
119pub trait HashSetExt {
123 type Item;
124
125 #[must_use]
126 fn new() -> Self;
127
128 #[must_use]
130 fn to_owned_vec(&self) -> Vec<Self::Item>;
131}
132
133impl<T: Clone> HashSetExt for HashSet<T> {
134 type Item = T;
135
136 fn new() -> Self {
137 HashSet::default()
138 }
139
140 fn to_owned_vec(&self) -> Vec<Self::Item> {
141 self.iter().cloned().collect()
142 }
143}
144
145impl<T: Clone> HashSetExt for IndexSet<T> {
146 type Item = T;
147
148 fn new() -> Self {
149 IndexSet::default()
150 }
151
152 fn to_owned_vec(&self) -> Vec<Self::Item> {
153 self.iter().cloned().collect()
154 }
155}
156
157#[must_use]
159pub fn hash_str(data: &str) -> u64 {
160 let mut hasher = rustc_hash::FxHasher::default();
161 hasher.write(data.as_bytes());
162 hasher.finish()
163}
164
165#[must_use]
168pub(crate) fn finish_deterministic_hash_128(hasher: DeterministicHasher) -> HashValueType {
169 hasher.digest128()
170}
171
172#[must_use]
174pub fn one_shot_128<T: Hash>(value: &T) -> u128 {
175 let mut hasher = DeterministicHasher::default();
176 value.hash(&mut hasher);
177 finish_deterministic_hash_128(hasher)
178}
179
180#[cfg(test)]
181mod tests {
182 use std::hash::Hash;
183
184 use super::*;
185
186 #[test]
187 fn hashes_strings() {
188 let a = one_shot_128(&"hello");
189 let b = one_shot_128(&"hello");
190 let c = one_shot_128(&"world");
191 assert_eq!(a, b);
192 assert_ne!(a, c);
193 }
194
195 #[test]
196 fn hashes_structs() {
197 #[derive(Hash)]
198 struct S {
199 x: u32,
200 y: String,
201 }
202 let h1 = one_shot_128(&S {
203 x: 1,
204 y: "a".into(),
205 });
206 let h2 = one_shot_128(&S {
207 x: 1,
208 y: "a".into(),
209 });
210 assert_eq!(h1, h2);
211 }
212
213 #[test]
214 fn hashing_tuple_matches_hashing_components_in_order() {
215 let tuple = ("John", 25_u32, true);
216
217 let mut hasher = DeterministicHasher::default();
218 tuple.0.hash(&mut hasher);
219 tuple.1.hash(&mut hasher);
220 tuple.2.hash(&mut hasher);
221
222 assert_eq!(finish_deterministic_hash_128(hasher), one_shot_128(&tuple));
223 }
224}