fasthash_fork/
murmur3.rs

1//! `Murmur3`, a suite of non-cryptographic hash functions that was used for hash-based lookups.
2//!
3//! by Austin Appleby (aappleby (AT) gmail)
4//!
5//! https://sites.google.com/site/murmurhash/
6//!
7//! # Note
8//!
9//! The x86 and x64 versions do _not_ produce the same results, as the
10//! algorithms are optimized for their respective platforms. You can still
11//! compile and run any of them on any platform, but your performance with the
12//! non-native version will be less than optimal.
13//!
14//! # Example
15//!
16//! ```
17//! use std::hash::{Hash, Hasher};
18//!
19//! use fasthash::{murmur3, Murmur3HasherExt};
20//!
21//! fn hash<T: Hash>(t: &T) -> u64 {
22//!     let mut s: Murmur3HasherExt = Default::default();
23//!     t.hash(&mut s);
24//!     s.finish()
25//! }
26//!
27//! let h = murmur3::hash128(b"hello world\xff");
28//!
29//! assert_eq!(h as u64, hash(&"hello world"));
30//! ```
31//!
32#![allow(non_camel_case_types)]
33use std::os::raw::c_void;
34
35use crate::ffi;
36
37use crate::hasher::FastHash;
38
39/// `MurmurHash3` 32-bit hash functions
40///
41/// # Example
42///
43/// ```
44/// use fasthash::{murmur3::Hash32, FastHash};
45///
46/// assert_eq!(Hash32::hash(b"hello"), 613153351);
47/// assert_eq!(Hash32::hash_with_seed(b"hello", 123), 1573043710);
48/// assert_eq!(Hash32::hash(b"helloworld"), 2687965642);
49/// ```
50#[derive(Clone, Default)]
51pub struct Hash32;
52
53impl FastHash for Hash32 {
54    type Hash = u32;
55    type Seed = u32;
56
57    #[inline(always)]
58    fn hash_with_seed<T: AsRef<[u8]>>(bytes: T, seed: u32) -> u32 {
59        unsafe {
60            let mut hash = 0_u32;
61
62            ffi::MurmurHash3_x86_32(
63                bytes.as_ref().as_ptr() as *const c_void,
64                bytes.as_ref().len() as i32,
65                seed,
66                &mut hash as *mut u32 as *mut c_void,
67            );
68
69            hash
70        }
71    }
72}
73
74trivial_hasher! {
75    /// # Example
76    ///
77    /// ```
78    /// use std::hash::Hasher;
79    ///
80    /// use fasthash::{murmur3::Hasher32, FastHasher};
81    ///
82    /// let mut h = Hasher32::new();
83    ///
84    /// h.write(b"hello");
85    /// assert_eq!(h.finish(), 613153351);
86    ///
87    /// h.write(b"world");
88    /// assert_eq!(h.finish(), 2687965642);
89    /// ```
90    Hasher32(Hash32) -> u32
91}
92
93/// `MurmurHash3` 128-bit hash functions for 32-bit processors
94///
95/// # Example
96///
97/// ```
98/// use fasthash::{murmur3::Hash128_x86, FastHash};
99///
100/// assert_eq!(
101///     Hash128_x86::hash(b"hello"),
102///     205839232668418009241864179939306390688
103/// );
104/// assert_eq!(
105///     Hash128_x86::hash_with_seed(b"hello", 123),
106///     39646137218600763345533167485429249129
107/// );
108/// assert_eq!(
109///     Hash128_x86::hash(b"helloworld"),
110///     83212725615010754952022132390053357814
111/// );
112/// ```
113#[derive(Clone, Default)]
114pub struct Hash128_x86;
115
116impl FastHash for Hash128_x86 {
117    type Hash = u128;
118    type Seed = u32;
119
120    #[inline(always)]
121    fn hash_with_seed<T: AsRef<[u8]>>(bytes: T, seed: u32) -> u128 {
122        unsafe {
123            let mut hash = 0;
124
125            ffi::MurmurHash3_x86_128(
126                bytes.as_ref().as_ptr() as *const c_void,
127                bytes.as_ref().len() as i32,
128                seed,
129                &mut hash as *mut u128 as *mut c_void,
130            );
131
132            hash
133        }
134    }
135}
136
137trivial_hasher! {
138    /// # Example
139    ///
140    /// ```
141    /// use std::hash::Hasher;
142    ///
143    /// use fasthash::{murmur3::Hasher128_x86, FastHasher, HasherExt};
144    ///
145    /// let mut h = Hasher128_x86::new();
146    ///
147    /// h.write(b"hello");
148    /// assert_eq!(h.finish_ext(), 205839232668418009241864179939306390688);
149    ///
150    /// h.write(b"world");
151    /// assert_eq!(h.finish_ext(), 83212725615010754952022132390053357814);
152    /// ```
153    Hasher128_x86(Hash128_x86) -> u128
154}
155
156/// `MurmurHash3` 128-bit hash functions for 64-bit processors
157///
158/// # Example
159///
160/// ```
161/// use fasthash::{murmur3::Hash128_x64, FastHash};
162///
163/// assert_eq!(
164///     Hash128_x64::hash(b"hello"),
165///     121118445609844952839898260755277781762
166/// );
167/// assert_eq!(
168///     Hash128_x64::hash_with_seed(b"hello", 123),
169///     19243349499071459060235768594146641163
170/// );
171/// assert_eq!(
172///     Hash128_x64::hash(b"helloworld"),
173///     216280293825344914020777844322685271162
174/// );
175/// ```
176#[derive(Clone, Default)]
177pub struct Hash128_x64;
178
179impl FastHash for Hash128_x64 {
180    type Hash = u128;
181    type Seed = u32;
182
183    #[inline(always)]
184    fn hash_with_seed<T: AsRef<[u8]>>(bytes: T, seed: u32) -> u128 {
185        unsafe {
186            let mut hash = 0;
187
188            ffi::MurmurHash3_x64_128(
189                bytes.as_ref().as_ptr() as *const c_void,
190                bytes.as_ref().len() as i32,
191                seed,
192                &mut hash as *mut u128 as *mut c_void,
193            );
194
195            hash
196        }
197    }
198}
199
200trivial_hasher! {
201    /// # Example
202    ///
203    /// ```
204    /// use std::hash::Hasher;
205    ///
206    /// use fasthash::{murmur3::Hasher128_x64, FastHasher, HasherExt};
207    ///
208    /// let mut h = Hasher128_x64::new();
209    ///
210    /// h.write(b"hello");
211    /// assert_eq!(h.finish_ext(), 121118445609844952839898260755277781762);
212    ///
213    /// h.write(b"world");
214    /// assert_eq!(h.finish_ext(), 216280293825344914020777844322685271162);
215    /// ```
216    Hasher128_x64(Hash128_x64) -> u128
217}
218
219/// `MurmurHash3` 32-bit hash functions for a byte array.
220#[inline(always)]
221pub fn hash32<T: AsRef<[u8]>>(v: T) -> u32 {
222    Hash32::hash(v)
223}
224
225/// `MurmurHash3` 32-bit hash functions for a byte array.
226/// For convenience, a 32-bit seed is also hashed into the result.
227#[inline(always)]
228pub fn hash32_with_seed<T: AsRef<[u8]>>(v: T, seed: u32) -> u32 {
229    Hash32::hash_with_seed(v, seed)
230}
231
232/// `MurmurHash3` 128-bit hash functions for a byte array.
233#[inline(always)]
234pub fn hash128<T: AsRef<[u8]>>(v: T) -> u128 {
235    if cfg!(target_pointer_width = "64") {
236        Hash128_x64::hash(v)
237    } else {
238        Hash128_x86::hash(v)
239    }
240}
241
242/// `MurmurHash3` 128-bit hash functions for a byte array.
243/// For convenience, a 32-bit seed is also hashed into the result.
244#[inline(always)]
245pub fn hash128_with_seed<T: AsRef<[u8]>>(v: T, seed: u32) -> u128 {
246    if cfg!(target_pointer_width = "64") {
247        Hash128_x64::hash_with_seed(v, seed)
248    } else {
249        Hash128_x86::hash_with_seed(v, seed)
250    }
251}