stable_hash/fast/
hasher.rs1use std::convert::TryInto;
2
3use super::fld::FldMix;
4use crate::prelude::*;
5
6#[derive(PartialEq, Eq, Hash, Clone, Debug)]
7pub struct FastStableHasher {
8 mixer: FldMix,
9 count: u64,
10}
11
12#[cfg(test)]
13impl FastStableHasher {
14 pub(crate) fn rand() -> Self {
15 use rand::thread_rng as rng;
16 use rand::Rng as _;
17 Self {
18 mixer: FldMix::rand(),
19 count: rng().gen(),
20 }
21 }
22}
23
24impl StableHasher for FastStableHasher {
25 type Out = u128;
26 type Addr = u128;
27 type Bytes = [u8; 32];
28
29 fn new() -> Self {
30 Self {
31 mixer: FldMix::new(),
32 count: 0,
33 }
34 }
35
36 fn mixin(&mut self, other: &Self) {
37 self.mixer.mixin(&other.mixer);
38 self.count = self.count.wrapping_add(other.count);
39 }
40
41 fn unmix(&mut self, other: &Self) {
42 self.mixer.unmix(&other.mixer);
43 self.count = self.count.wrapping_sub(other.count);
44 }
45
46 fn to_bytes(&self) -> Self::Bytes {
47 let mixer = self.mixer.to_bytes();
48 let count = self.count.to_le_bytes();
49
50 let mut bytes = [0; 32];
51 bytes[0..24].copy_from_slice(&mixer);
52 bytes[24..32].copy_from_slice(&count);
53
54 bytes
55 }
56
57 fn from_bytes(bytes: Self::Bytes) -> Self {
58 Self {
59 mixer: FldMix::from_bytes(bytes[0..24].try_into().unwrap()),
60 count: u64::from_le_bytes(bytes[24..32].try_into().unwrap()),
61 }
62 }
63
64 fn write(&mut self, field_address: Self::Addr, bytes: &[u8]) {
65 profile_method!(write);
66
67 let hash = xxhash_rust::xxh3::xxh3_128_with_seed(bytes, field_address as u64);
74 self.mixer.mix(hash, (field_address >> 64) as u64);
75 self.count += 1;
76 }
77
78 fn finish(&self) -> u128 {
79 profile_method!(finish);
80 xxhash_rust::xxh3::xxh3_128_with_seed(&self.mixer.to_bytes(), self.count)
81 }
82}