1#![deny(missing_docs)]
12
13use std::collections::{HashMap, HashSet};
29use std::default::Default;
30use std::hash::{Hasher, Hash, BuildHasherDefault};
31use std::ops::BitXor;
32
33extern crate byteorder;
34use byteorder::{ByteOrder, NativeEndian};
35
36pub type FxBuildHasher = BuildHasherDefault<FxHasher>;
38
39pub type FxHashMap<K, V> = HashMap<K, V, FxBuildHasher>;
41
42pub type FxHashSet<V> = HashSet<V, FxBuildHasher>;
44
45const ROTATE: u32 = 5;
46const SEED64: u64 = 0x517cc1b727220a95;
47const SEED32: u32 = (SEED64 & 0xFFFF_FFFF) as u32;
48
49#[cfg(target_pointer_width = "32")]
50const SEED: usize = SEED32 as usize;
51#[cfg(target_pointer_width = "64")]
52const SEED: usize = SEED64 as usize;
53
54trait HashWord {
55 fn hash_word(&mut self, Self);
56}
57
58macro_rules! impl_hash_word {
59 ($($ty:ty = $key:ident),* $(,)*) => (
60 $(
61 impl HashWord for $ty {
62 #[inline]
63 fn hash_word(&mut self, word: Self) {
64 *self = self.rotate_left(ROTATE).bitxor(word).wrapping_mul($key);
65 }
66 }
67 )*
68 )
69}
70
71impl_hash_word!(usize = SEED, u32 = SEED32, u64 = SEED64);
72
73#[inline]
74fn write32(mut hash: u32, mut bytes: &[u8]) -> u32 {
75 while bytes.len() >= 4 {
76 let n = NativeEndian::read_u32(bytes);
77 hash.hash_word(n);
78 bytes = bytes.split_at(4).1;
79 }
80
81 for byte in bytes {
82 hash.hash_word(*byte as u32);
83 }
84 hash
85}
86
87#[inline]
88fn write64(mut hash: u64, mut bytes: &[u8]) -> u64 {
89 while bytes.len() >= 8 {
90 let n = NativeEndian::read_u64(bytes);
91 hash.hash_word(n);
92 bytes = bytes.split_at(8).1;
93 }
94
95 if bytes.len() >= 4 {
96 let n = NativeEndian::read_u32(bytes);
97 hash.hash_word(n as u64);
98 bytes = bytes.split_at(4).1;
99 }
100
101 for byte in bytes {
102 hash.hash_word(*byte as u64);
103 }
104 hash
105}
106
107#[inline]
108#[cfg(target_pointer_width = "32")]
109fn write(hash: usize, bytes: &[u8]) -> usize {
110 write32(hash as u32, bytes) as usize
111}
112
113#[inline]
114#[cfg(target_pointer_width = "64")]
115fn write(hash: usize, bytes: &[u8]) -> usize {
116 write64(hash as u64, bytes) as usize
117}
118
119#[derive(Debug, Clone)]
127pub struct FxHasher {
128 hash: usize,
129}
130
131impl Default for FxHasher {
132 #[inline]
133 fn default() -> FxHasher {
134 FxHasher { hash: 0 }
135 }
136}
137
138impl Hasher for FxHasher {
139 #[inline]
140 fn write(&mut self, bytes: &[u8]) {
141 self.hash = write(self.hash, bytes);
142 }
143
144 #[inline]
145 fn write_u8(&mut self, i: u8) {
146 self.hash.hash_word(i as usize);
147 }
148
149 #[inline]
150 fn write_u16(&mut self, i: u16) {
151 self.hash.hash_word(i as usize);
152 }
153
154 #[inline]
155 fn write_u32(&mut self, i: u32) {
156 self.hash.hash_word(i as usize);
157 }
158
159 #[inline]
160 #[cfg(target_pointer_width = "32")]
161 fn write_u64(&mut self, i: u64) {
162 self.hash.hash_word(i as usize);
163 self.hash.hash_word((i >> 32) as usize);
164 }
165
166 #[inline]
167 #[cfg(target_pointer_width = "64")]
168 fn write_u64(&mut self, i: u64) {
169 self.hash.hash_word(i as usize);
170 }
171
172 #[inline]
173 fn write_usize(&mut self, i: usize) {
174 self.hash.hash_word(i);
175 }
176
177 #[inline]
178 fn finish(&self) -> u64 {
179 self.hash as u64
180 }
181}
182
183#[derive(Debug, Clone)]
191pub struct FxHasher64 {
192 hash: u64,
193}
194
195impl Default for FxHasher64 {
196 #[inline]
197 fn default() -> FxHasher64 {
198 FxHasher64 { hash: 0 }
199 }
200}
201
202impl Hasher for FxHasher64 {
203 #[inline]
204 fn write(&mut self, bytes: &[u8]) {
205 self.hash = write64(self.hash, bytes);
206 }
207
208 #[inline]
209 fn write_u8(&mut self, i: u8) {
210 self.hash.hash_word(i as u64);
211 }
212
213 #[inline]
214 fn write_u16(&mut self, i: u16) {
215 self.hash.hash_word(i as u64);
216 }
217
218 #[inline]
219 fn write_u32(&mut self, i: u32) {
220 self.hash.hash_word(i as u64);
221 }
222
223 fn write_u64(&mut self, i: u64) {
224 self.hash.hash_word(i);
225 }
226
227 #[inline]
228 fn write_usize(&mut self, i: usize) {
229 self.hash.hash_word(i as u64);
230 }
231
232 #[inline]
233 fn finish(&self) -> u64 {
234 self.hash
235 }
236}
237
238#[derive(Debug, Clone)]
246pub struct FxHasher32 {
247 hash: u32,
248}
249
250impl Default for FxHasher32 {
251 #[inline]
252 fn default() -> FxHasher32 {
253 FxHasher32 { hash: 0 }
254 }
255}
256
257impl Hasher for FxHasher32 {
258 #[inline]
259 fn write(&mut self, bytes: &[u8]) {
260 self.hash = write32(self.hash, bytes);
261 }
262
263 #[inline]
264 fn write_u8(&mut self, i: u8) {
265 self.hash.hash_word(i as u32);
266 }
267
268 #[inline]
269 fn write_u16(&mut self, i: u16) {
270 self.hash.hash_word(i as u32);
271 }
272
273 #[inline]
274 fn write_u32(&mut self, i: u32) {
275 self.hash.hash_word(i);
276 }
277
278 #[inline]
279 fn write_u64(&mut self, i: u64) {
280 self.hash.hash_word(i as u32);
281 self.hash.hash_word((i >> 32) as u32);
282 }
283
284 #[inline]
285 #[cfg(target_pointer_width = "32")]
286 fn write_usize(&mut self, i: usize) {
287 self.write_u32(i as u32);
288 }
289
290 #[inline]
291 #[cfg(target_pointer_width = "64")]
292 fn write_usize(&mut self, i: usize) {
293 self.write_u64(i as u64);
294 }
295
296 #[inline]
297 fn finish(&self) -> u64 {
298 self.hash as u64
299 }
300}
301
302#[inline]
304pub fn hash64<T: Hash + ?Sized>(v: &T) -> u64 {
305 let mut state = FxHasher64::default();
306 v.hash(&mut state);
307 state.finish()
308}
309
310#[inline]
312pub fn hash32<T: Hash + ?Sized>(v: &T) -> u32 {
313 let mut state = FxHasher32::default();
314 v.hash(&mut state);
315 state.finish() as u32
316}
317
318#[inline]
320pub fn hash<T: Hash + ?Sized>(v: &T) -> usize {
321 let mut state = FxHasher::default();
322 v.hash(&mut state);
323 state.finish() as usize
324}