cityhash_sys/
hasher.rs

1use crate::{city_hash_128_to_64, city_hash_128, city_hash_128_with_seed, city_hash_32, city_hash_64, city_hash_64_with_seed};
2use core::hash::{BuildHasher, BuildHasherDefault, Hasher};
3
4/// 64-bits CityHash hasher
5#[derive(Debug, Default)]
6pub struct CityHash64Hasher {
7    key: Option<u64>,
8}
9
10impl CityHash64Hasher {
11    /// Create a new [CityHash64Hasher] initiated with a hash key
12    pub fn with_seed(seed: u64) -> CityHash64Hasher {
13        CityHash64Hasher { key: Some(seed) }
14    }
15}
16
17impl Hasher for CityHash64Hasher {
18    /// Returns the hash value for the values written so far.
19    ///
20    /// # Example
21    ///
22    /// ```
23    /// use cityhash_sys::CityHash64Hasher;
24    /// use core::hash::Hasher;
25    ///
26    /// let hasher = CityHash64Hasher::with_seed(0xB4BFA9E87732C149);
27    /// assert_eq!(hasher.finish(), 0xB4BFA9E87732C149);
28    /// ```
29    fn finish(&self) -> u64 {
30        self.key.unwrap_or(0)
31    }
32
33    /// Writes some data into the [CityHash64Hasher].
34    ///
35    /// # Example
36    ///
37    /// ```
38    /// use cityhash_sys::CityHash64Hasher;
39    /// use core::hash::Hasher;
40    ///
41    /// let mut hasher = CityHash64Hasher::default();
42    /// hasher.write(b"hash me!");
43    /// ```
44    fn write(&mut self, bytes: &[u8]) {
45        self.key = Some(match self.key {
46            None => city_hash_64(bytes),
47            Some(seed) => city_hash_64_with_seed(bytes, seed),
48        })
49    }
50}
51
52impl BuildHasher for CityHash64Hasher {
53    type Hasher = CityHash64Hasher;
54
55    /// Creates a new [CityHash64Hasher].
56    fn build_hasher(&self) -> Self::Hasher {
57        CityHash64Hasher::default()
58    }
59}
60
61/// 32-bits CityHash hasher
62#[derive(Debug, Default)]
63pub struct CityHash32Hasher {
64    key: Option<u32>,
65}
66
67impl CityHash32Hasher {
68    /// Create a new [CityHash32Hasher] initiated with a hash key
69    pub fn with_seed(seed: u32) -> CityHash32Hasher {
70        CityHash32Hasher { key: Some(seed) }
71    }
72}
73
74impl Hasher for CityHash32Hasher {
75    /// Returns the hash value for the values written so far.
76    ///
77    /// # Example
78    ///
79    /// ```
80    /// use cityhash_sys::CityHash32Hasher;
81    /// use core::hash::Hasher;
82    ///
83    /// let hasher = CityHash32Hasher::with_seed(0xB4BFA9E);
84    /// assert_eq!(hasher.finish(), 0xB4BFA9E);
85    /// ```
86    fn finish(&self) -> u64 {
87        if let Some(hash) = self.key {
88            hash as u64
89        } else {
90            0
91        }
92    }
93
94    /// Writes some data into the [CityHash32Hasher].
95    ///
96    /// # Example
97    ///
98    /// ```
99    /// use cityhash_sys::CityHash32Hasher;
100    /// use core::hash::Hasher;
101    ///
102    /// let mut hasher = CityHash32Hasher::default();
103    /// hasher.write(b"hash me!");
104    /// ```
105    fn write(&mut self, bytes: &[u8]) {
106        self.key = Some(match self.key {
107            None => city_hash_32(bytes),
108            Some(mut seed) => {
109                let mut key = city_hash_32(bytes);
110
111                // Mix of 2 u32 based on Murmur3.
112                // Magic numbers for 32-bit hashing. 
113                const C1: u32 = 0xcc9e2d51;
114                const C2: u32 = 0x1b873593;
115
116                // Combine 2 32-bits values from Murmur3
117                key = key.wrapping_mul(C1);
118                key = key.rotate_right(17);
119                key = key.wrapping_mul(C2);
120                seed ^= key;
121                seed = seed.rotate_right(19);
122                seed.wrapping_mul(5).wrapping_add(0xe6546b64)
123            }
124        })
125    }
126}
127
128impl BuildHasher for CityHash32Hasher {
129    type Hasher = CityHash32Hasher;
130
131    /// Creates a new [CityHash32Hasher].
132    fn build_hasher(&self) -> Self::Hasher {
133        CityHash32Hasher::default()
134    }
135}
136
137/// 128-bits CityHash hasher
138#[derive(Debug, Default)]
139pub struct CityHash128Hasher {
140    key: Option<u128>,
141}
142
143impl CityHash128Hasher {
144    /// Create a new [CityHash128Hasher] initiated with a hash key
145    pub fn with_seed(seed: u128) -> CityHash128Hasher {
146        CityHash128Hasher { key: Some(seed) }
147    }
148}
149
150impl Hasher for CityHash128Hasher {
151    /// Returns the hash value for the values written so far.
152    /// The hash is compress to a 64-bits with [city_hash_128_to_64]
153    ///
154    /// # Example
155    ///
156    /// ```
157    /// use cityhash_sys::CityHash128Hasher;
158    /// use core::hash::Hasher;
159    ///
160    /// let hasher = CityHash128Hasher::with_seed(0xAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBB);
161    /// assert_eq!(hasher.finish(), 0x88FC029FFEBB98B4);
162    /// ```
163    fn finish(&self) -> u64 {
164        if let Some(hash) = self.key {
165            city_hash_128_to_64(hash)
166        } else {
167            0
168        }
169    }
170
171    /// Writes some data into the [CityHash128Hasher].
172    ///
173    /// # Example
174    ///
175    /// ```
176    /// use cityhash_sys::CityHash128Hasher;
177    /// use core::hash::Hasher;
178    ///
179    /// let mut hasher = CityHash128Hasher::default();
180    /// hasher.write(b"hash me!");
181    /// ```
182    fn write(&mut self, bytes: &[u8]) {
183        self.key = Some(match self.key {
184            None => city_hash_128(bytes),
185            Some(seed) => city_hash_128_with_seed(bytes, seed),
186        })
187    }
188}
189
190impl BuildHasher for CityHash128Hasher {
191    type Hasher = CityHash128Hasher;
192
193    /// Creates a new [CityHash128Hasher].
194    fn build_hasher(&self) -> Self::Hasher {
195        CityHash128Hasher::default()
196    }
197}
198
199/// A builder for default 32-bits CityHash hashers.
200pub type CityHash32BuildHasher = BuildHasherDefault<CityHash32Hasher>;
201
202/// A builder for default 64-bits CityHash hashers.
203pub type CityHash64BuildHasher = BuildHasherDefault<CityHash64Hasher>;
204
205/// A builder for default 128-bits CityHash hashers.
206pub type CityHash128BuildHasher = BuildHasherDefault<CityHash128Hasher>;
207
208/// A builder for default CityHash hashers.
209pub type CityHashBuildHasher = CityHash64BuildHasher;