Skip to main content

oxide_core/heap/
hash.rs

1//! A small multiplicative hasher for the heap's internal tables, whose keys are
2//! 32-bit indices and are not attacker-chosen hash-flooding inputs.
3
4use std::collections::HashMap;
5use std::hash::{BuildHasherDefault, Hasher};
6
7const SEED: u64 = 0x51_7c_c1_b7_27_22_0a_95;
8
9#[derive(Default, Clone, Copy)]
10pub struct FxHasher {
11    hash: u64,
12}
13
14impl FxHasher {
15    #[inline]
16    fn add(&mut self, word: u64) {
17        self.hash = (self.hash.rotate_left(5) ^ word).wrapping_mul(SEED);
18    }
19}
20
21impl Hasher for FxHasher {
22    #[inline]
23    fn write(&mut self, bytes: &[u8]) {
24        for chunk in bytes.chunks(8) {
25            let mut word = [0u8; 8];
26            word[..chunk.len()].copy_from_slice(chunk);
27            self.add(u64::from_le_bytes(word));
28        }
29    }
30
31    #[inline]
32    fn write_u8(&mut self, value: u8) {
33        self.add(u64::from(value));
34    }
35
36    #[inline]
37    fn write_u32(&mut self, value: u32) {
38        self.add(u64::from(value));
39    }
40
41    #[inline]
42    fn write_u64(&mut self, value: u64) {
43        self.add(value);
44    }
45
46    #[inline]
47    fn write_usize(&mut self, value: usize) {
48        self.add(value as u64);
49    }
50
51    #[inline]
52    fn finish(&self) -> u64 {
53        self.hash
54    }
55}
56
57pub type FxHashMap<K, V> = HashMap<K, V, BuildHasherDefault<FxHasher>>;
58pub type FxHashSet<K> = std::collections::HashSet<K, BuildHasherDefault<FxHasher>>;