pub fn hash_string(s: &str) -> u64 {
murmur_hash_64a(s.as_bytes(), 1)
}
fn murmur_hash_64a(key: &[u8], seed: u64) -> u64 {
const M: u64 = 0xc6a4_a793_5bd1_e995;
const R: u32 = 47;
let mut h = seed ^ (key.len() as u64).wrapping_mul(M);
let (blocks, tail) = key.as_chunks::<8>();
for block in blocks {
let mut k = u64::from_le_bytes(*block);
k = k.wrapping_mul(M);
k ^= k >> R;
k = k.wrapping_mul(M);
h ^= k;
h = h.wrapping_mul(M);
}
if !tail.is_empty() {
for (i, &b) in tail.iter().enumerate() {
h ^= u64::from(b) << (8 * i);
}
h = h.wrapping_mul(M);
}
h ^= h >> R;
h = h.wrapping_mul(M);
h ^= h >> R;
h
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn matches_spacy_hash_string() {
assert_eq!(hash_string("because"), 16950148841647037698);
assert_eq!(hash_string("a"), 11901859001352538922);
assert_eq!(hash_string("colour"), 2579953423244470672);
assert_eq!(hash_string(" "), 8532415787641010193);
assert_eq!(hash_string("héllo wörld!"), 15695761827416483309);
assert_eq!(hash_string("12345678"), 9871996032675327904);
assert_eq!(hash_string("123456789abcdefgh"), 4275926136390810747);
}
}