conspire/math/hash/
mod.rs1#[cfg(test)]
2mod test;
3
4use std::{
5 collections::{HashMap, HashSet},
6 hash::{BuildHasherDefault, Hasher},
7};
8
9const SEED: u64 = 0x51_7c_c1_b7_27_22_0a_95;
10const ROTATE: u32 = 5;
11
12pub type FxHashMap<K, V> = HashMap<K, V, BuildHasherDefault<FxHasher>>;
17
18pub type FxHashSet<T> = HashSet<T, BuildHasherDefault<FxHasher>>;
22
23#[derive(Default)]
28pub struct FxHasher {
29 hash: u64,
30}
31
32impl FxHasher {
33 #[inline]
34 fn add(&mut self, word: u64) {
35 self.hash = (self.hash.rotate_left(ROTATE) ^ word).wrapping_mul(SEED);
36 }
37}
38
39impl Hasher for FxHasher {
40 #[inline]
41 fn write(&mut self, mut bytes: &[u8]) {
42 while let Some((word, rest)) = bytes.split_first_chunk::<8>() {
43 self.add(u64::from_le_bytes(*word));
44 bytes = rest;
45 }
46 if let Some((word, rest)) = bytes.split_first_chunk::<4>() {
47 self.add(u32::from_le_bytes(*word) as u64);
48 bytes = rest;
49 }
50 if let Some((word, rest)) = bytes.split_first_chunk::<2>() {
51 self.add(u16::from_le_bytes(*word) as u64);
52 bytes = rest;
53 }
54 if let Some(&byte) = bytes.first() {
55 self.add(byte as u64);
56 }
57 }
58 #[inline]
59 fn write_u8(&mut self, value: u8) {
60 self.add(value as u64);
61 }
62 #[inline]
63 fn write_u16(&mut self, value: u16) {
64 self.add(value as u64);
65 }
66 #[inline]
67 fn write_u32(&mut self, value: u32) {
68 self.add(value as u64);
69 }
70 #[inline]
71 fn write_u64(&mut self, value: u64) {
72 self.add(value);
73 }
74 #[inline]
75 fn write_usize(&mut self, value: usize) {
76 self.add(value as u64);
77 }
78 #[inline]
79 fn finish(&self) -> u64 {
80 self.hash
81 }
82}