1#![deny(missing_docs)]
12
13#![cfg_attr(not(feature = "std"), no_std)]
15
16#[allow(unused_extern_crates)]
33#[cfg(all(feature = "hashmap_core", not(feature = "std")))]
34extern crate hashmap_core;
35
36use std::default::Default;
37use std::hash::{Hasher, Hash, BuildHasherDefault};
38use std::ops::BitXor;
39
40extern crate byteorder;
41#[macro_use]
42extern crate cfg_if;
43use byteorder::{ByteOrder, NativeEndian};
44
45pub type FxBuildHasher = BuildHasherDefault<FxHasher>;
47
48cfg_if! {
49 if #[cfg(any(feature = "hashmap-core", feature = "std"))] {
50 use std::collections::{HashMap, HashSet};
51
52 pub type FxHashMap<K, V> = HashMap<K, V, FxBuildHasher>;
54
55 pub type FxHashSet<V> = HashSet<V, FxBuildHasher>;
57 }
58}
59
60const ROTATE: u32 = 5;
61const SEED64: u64 = 0x517cc1b727220a95;
62const SEED32: u32 = (SEED64 & 0xFFFF_FFFF) as u32;
63
64#[cfg(target_pointer_width = "32")]
65const SEED: usize = SEED32 as usize;
66#[cfg(target_pointer_width = "64")]
67const SEED: usize = SEED64 as usize;
68
69trait HashWord {
70 fn hash_word(&mut self, Self);
71}
72
73macro_rules! impl_hash_word {
74 ($($ty:ty = $key:ident),* $(,)*) => (
75 $(
76 impl HashWord for $ty {
77 #[inline]
78 fn hash_word(&mut self, word: Self) {
79 *self = self.rotate_left(ROTATE).bitxor(word).wrapping_mul($key);
80 }
81 }
82 )*
83 )
84}
85
86impl_hash_word!(usize = SEED, u32 = SEED32, u64 = SEED64);
87
88#[inline]
89fn write32(mut hash: u32, mut bytes: &[u8]) -> u32 {
90 while bytes.len() >= 4 {
91 let n = NativeEndian::read_u32(bytes);
92 hash.hash_word(n);
93 bytes = bytes.split_at(4).1;
94 }
95
96 for byte in bytes {
97 hash.hash_word(*byte as u32);
98 }
99 hash
100}
101
102#[inline]
103fn write64(mut hash: u64, mut bytes: &[u8]) -> u64 {
104 while bytes.len() >= 8 {
105 let n = NativeEndian::read_u64(bytes);
106 hash.hash_word(n);
107 bytes = bytes.split_at(8).1;
108 }
109
110 if bytes.len() >= 4 {
111 let n = NativeEndian::read_u32(bytes);
112 hash.hash_word(n as u64);
113 bytes = bytes.split_at(4).1;
114 }
115
116 for byte in bytes {
117 hash.hash_word(*byte as u64);
118 }
119 hash
120}
121
122#[inline]
123#[cfg(target_pointer_width = "32")]
124fn write(hash: usize, bytes: &[u8]) -> usize {
125 write32(hash as u32, bytes) as usize
126}
127
128#[inline]
129#[cfg(target_pointer_width = "64")]
130fn write(hash: usize, bytes: &[u8]) -> usize {
131 write64(hash as u64, bytes) as usize
132}
133
134#[derive(Debug, Clone)]
142pub struct FxHasher {
143 hash: usize,
144}
145
146impl Default for FxHasher {
147 #[inline]
148 fn default() -> FxHasher {
149 FxHasher { hash: 0 }
150 }
151}
152
153impl Hasher for FxHasher {
154 #[inline]
155 fn write(&mut self, bytes: &[u8]) {
156 self.hash = write(self.hash, bytes);
157 }
158
159 #[inline]
160 fn write_u8(&mut self, i: u8) {
161 self.hash.hash_word(i as usize);
162 }
163
164 #[inline]
165 fn write_u16(&mut self, i: u16) {
166 self.hash.hash_word(i as usize);
167 }
168
169 #[inline]
170 fn write_u32(&mut self, i: u32) {
171 self.hash.hash_word(i as usize);
172 }
173
174 #[inline]
175 #[cfg(target_pointer_width = "32")]
176 fn write_u64(&mut self, i: u64) {
177 self.hash.hash_word(i as usize);
178 self.hash.hash_word((i >> 32) as usize);
179 }
180
181 #[inline]
182 #[cfg(target_pointer_width = "64")]
183 fn write_u64(&mut self, i: u64) {
184 self.hash.hash_word(i as usize);
185 }
186
187 #[inline]
188 fn write_usize(&mut self, i: usize) {
189 self.hash.hash_word(i);
190 }
191
192 #[inline]
193 fn finish(&self) -> u64 {
194 self.hash as u64
195 }
196}
197
198#[derive(Debug, Clone)]
206pub struct FxHasher64 {
207 hash: u64,
208}
209
210impl Default for FxHasher64 {
211 #[inline]
212 fn default() -> FxHasher64 {
213 FxHasher64 { hash: 0 }
214 }
215}
216
217impl Hasher for FxHasher64 {
218 #[inline]
219 fn write(&mut self, bytes: &[u8]) {
220 self.hash = write64(self.hash, bytes);
221 }
222
223 #[inline]
224 fn write_u8(&mut self, i: u8) {
225 self.hash.hash_word(i as u64);
226 }
227
228 #[inline]
229 fn write_u16(&mut self, i: u16) {
230 self.hash.hash_word(i as u64);
231 }
232
233 #[inline]
234 fn write_u32(&mut self, i: u32) {
235 self.hash.hash_word(i as u64);
236 }
237
238 fn write_u64(&mut self, i: u64) {
239 self.hash.hash_word(i);
240 }
241
242 #[inline]
243 fn write_usize(&mut self, i: usize) {
244 self.hash.hash_word(i as u64);
245 }
246
247 #[inline]
248 fn finish(&self) -> u64 {
249 self.hash
250 }
251}
252
253#[derive(Debug, Clone)]
261pub struct FxHasher32 {
262 hash: u32,
263}
264
265impl Default for FxHasher32 {
266 #[inline]
267 fn default() -> FxHasher32 {
268 FxHasher32 { hash: 0 }
269 }
270}
271
272impl Hasher for FxHasher32 {
273 #[inline]
274 fn write(&mut self, bytes: &[u8]) {
275 self.hash = write32(self.hash, bytes);
276 }
277
278 #[inline]
279 fn write_u8(&mut self, i: u8) {
280 self.hash.hash_word(i as u32);
281 }
282
283 #[inline]
284 fn write_u16(&mut self, i: u16) {
285 self.hash.hash_word(i as u32);
286 }
287
288 #[inline]
289 fn write_u32(&mut self, i: u32) {
290 self.hash.hash_word(i);
291 }
292
293 #[inline]
294 fn write_u64(&mut self, i: u64) {
295 self.hash.hash_word(i as u32);
296 self.hash.hash_word((i >> 32) as u32);
297 }
298
299 #[inline]
300 #[cfg(target_pointer_width = "32")]
301 fn write_usize(&mut self, i: usize) {
302 self.write_u32(i as u32);
303 }
304
305 #[inline]
306 #[cfg(target_pointer_width = "64")]
307 fn write_usize(&mut self, i: usize) {
308 self.write_u64(i as u64);
309 }
310
311 #[inline]
312 fn finish(&self) -> u64 {
313 self.hash as u64
314 }
315}
316
317#[inline]
319pub fn hash64<T: Hash + ?Sized>(v: &T) -> u64 {
320 let mut state = FxHasher64::default();
321 v.hash(&mut state);
322 state.finish()
323}
324
325#[inline]
327pub fn hash32<T: Hash + ?Sized>(v: &T) -> u32 {
328 let mut state = FxHasher32::default();
329 v.hash(&mut state);
330 state.finish() as u32
331}
332
333#[inline]
335pub fn hash<T: Hash + ?Sized>(v: &T) -> usize {
336 let mut state = FxHasher::default();
337 v.hash(&mut state);
338 state.finish() as usize
339}
340
341#[cfg(not(feature = "std"))]
343mod std {
344 pub use core::*;
345
346 #[cfg(feature = "hashmap-core")]
347 pub mod collections {
348 pub use hashmap_core::{HashMap, HashSet};
349 pub use hashmap_core::map as hash_map;
350 }
351}