growable_bloom_filter/
stable_hasher.rs

1use std::hash::Hasher;
2
3/// Wrapper over a hasher that provides stable output across platforms
4/// Based on https://github.com/rust-lang/rust/blob/c0955a34bcb17f0b31d7b86522a520ebe7fa93ac/src/librustc_data_structures/stable_hasher.rs#L78-L166
5///
6/// To that end we always convert integers to little-endian format before
7/// hashing and the architecture dependent `isize` and `usize` types are
8/// extended to 64 bits if needed.
9pub struct StableHasher {
10    /// Using xxh3-64 with default seed/secret as the portable hasher.
11    state: xxhash_rust::xxh3::Xxh3,
12}
13
14impl StableHasher {
15    #[inline]
16    pub fn new() -> Self {
17        Self {
18            state: xxhash_rust::xxh3::Xxh3::new(),
19        }
20    }
21}
22
23impl Hasher for StableHasher {
24    #[inline]
25    fn finish(&self) -> u64 {
26        self.state.finish()
27    }
28
29    #[inline]
30    fn write(&mut self, bytes: &[u8]) {
31        self.state.write(bytes);
32    }
33
34    #[inline]
35    fn write_u8(&mut self, i: u8) {
36        self.state.write_u8(i);
37    }
38
39    #[inline]
40    fn write_u16(&mut self, i: u16) {
41        self.state.write_u16(i.to_le());
42    }
43
44    #[inline]
45    fn write_u32(&mut self, i: u32) {
46        self.state.write_u32(i.to_le());
47    }
48
49    #[inline]
50    fn write_u64(&mut self, i: u64) {
51        self.state.write_u64(i.to_le());
52    }
53
54    #[inline]
55    fn write_u128(&mut self, i: u128) {
56        self.state.write_u128(i.to_le());
57    }
58
59    #[inline]
60    fn write_usize(&mut self, i: usize) {
61        // Always treat usize as u64 so we get the same results on 32 and 64 bit
62        // platforms. This is important for symbol hashes when cross compiling,
63        // for example.
64        self.state.write_u64((i as u64).to_le());
65    }
66
67    #[inline]
68    fn write_i8(&mut self, i: i8) {
69        self.state.write_i8(i);
70    }
71
72    #[inline]
73    fn write_i16(&mut self, i: i16) {
74        self.state.write_i16(i.to_le());
75    }
76
77    #[inline]
78    fn write_i32(&mut self, i: i32) {
79        self.state.write_i32(i.to_le());
80    }
81
82    #[inline]
83    fn write_i64(&mut self, i: i64) {
84        self.state.write_i64(i.to_le());
85    }
86
87    #[inline]
88    fn write_i128(&mut self, i: i128) {
89        self.state.write_i128(i.to_le());
90    }
91
92    #[inline]
93    fn write_isize(&mut self, i: isize) {
94        // Always treat isize as i64 so we get the same results on 32 and 64 bit
95        // platforms. This is important for symbol hashes when cross compiling,
96        // for example.
97        self.state.write_i64((i as i64).to_le());
98    }
99}