Skip to main content

sshash_lib/
hasher.rs

1//! Deterministic hasher for minimizers using rapidhash.
2//!
3//! This uses rapidhash with fixed seeds to provide deterministic hashing
4//! that is CPU-feature independent (unlike ahash which switches algorithm
5//! when AES-NI is available, breaking serialized indices).
6
7use rapidhash::fast::RapidHasher;
8use std::hash::Hasher;
9
10/// A deterministic hasher with a seeded state.
11///
12/// Uses rapidhash which produces identical results regardless of target CPU
13/// features, unlike ahash which uses different algorithms with/without AES-NI.
14#[derive(Clone)]
15pub struct DeterministicHasher {
16    seed: u64,
17}
18
19impl DeterministicHasher {
20    /// Create a new deterministic hasher with the given seed
21    pub fn new(seed: u64) -> Self {
22        Self { seed }
23    }
24
25    /// Hash a u64 value using a seeded RapidHasher
26    #[inline]
27    pub fn hash_u64(&self, value: u64) -> u64 {
28        let mut hasher = RapidHasher::new(self.seed);
29        hasher.write_u64(value);
30        hasher.finish()
31    }
32
33    /// Hash a u64 using the seeded hasher (for compatibility with iterator API)
34    pub fn hash(&self, value: u64) -> u64 {
35        self.hash_u64(value)
36    }
37
38    /// Get the seed value
39    pub fn seed(&self) -> u64 {
40        self.seed
41    }
42}
43
44#[cfg(test)]
45mod tests {
46    use super::*;
47
48    #[test]
49    fn test_deterministic_hashing() {
50        let hasher1 = DeterministicHasher::new(42);
51        let hasher2 = DeterministicHasher::new(42);
52        let hasher3 = DeterministicHasher::new(43);
53
54        let value = 0x123456789abcdef0u64;
55
56        // Same seed should produce same hash
57        assert_eq!(hasher1.hash(value), hasher2.hash(value));
58
59        // Different seed should produce different hash
60        assert_ne!(hasher1.hash(value), hasher3.hash(value));
61    }
62
63    #[test]
64    fn test_different_values_produce_different_hashes() {
65        let hasher = DeterministicHasher::new(1);
66
67        let hash1 = hasher.hash(100);
68        let hash2 = hasher.hash(101);
69
70        // Different inputs should produce different outputs
71        assert_ne!(hash1, hash2);
72    }
73}