use std::hash::{Hash, Hasher};
use twox_hash::XxHash64;
pub fn murmur3_hash(data: &[u8], seed: u32) -> u32 {
let mut hash = seed;
let len = data.len();
let chunks = len / 4;
for i in 0..chunks {
let k = u32::from_le_bytes([
data[i * 4],
data[i * 4 + 1],
data[i * 4 + 2],
data[i * 4 + 3],
]);
let k = k.wrapping_mul(0xcc9e2d51);
let k = k.rotate_left(15);
let k = k.wrapping_mul(0x1b873593);
hash ^= k;
hash = hash.rotate_left(13);
hash = hash.wrapping_mul(5).wrapping_add(0xe6546b64);
}
let remainder = len % 4;
if remainder > 0 {
let offset = chunks * 4;
let mut k: u32 = 0;
if remainder >= 3 {
k ^= (data[offset + 2] as u32) << 16;
}
if remainder >= 2 {
k ^= (data[offset + 1] as u32) << 8;
}
k ^= data[offset] as u32;
k = k.wrapping_mul(0xcc9e2d51);
k = k.rotate_left(15);
k = k.wrapping_mul(0x1b873593);
hash ^= k;
}
hash ^= len as u32;
hash ^= hash >> 16;
hash = hash.wrapping_mul(0x85ebca6b);
hash ^= hash >> 13;
hash = hash.wrapping_mul(0xc2b2ae35);
hash ^= hash >> 16;
hash
}
pub fn xxhash(data: &[u8], seed: u64) -> u64 {
let mut hasher = XxHash64::with_seed(seed);
hasher.write(data);
hasher.finish()
}
pub fn murmur3_hash64(data: &[u8], seed: u64) -> u64 {
xxhash(data, seed)
}
pub fn hash_64(data: &[u8], seed: u64) -> u64 {
xxhash(data, seed)
}
pub fn hash_value<T: Hash>(value: &T, seed: u32) -> u32 {
use std::hash::Hasher as StdHasher;
struct ByteHasher {
bytes: Vec<u8>,
}
impl StdHasher for ByteHasher {
fn finish(&self) -> u64 {
0 }
fn write(&mut self, bytes: &[u8]) {
self.bytes.extend_from_slice(bytes);
}
}
let mut hasher = ByteHasher { bytes: Vec::new() };
value.hash(&mut hasher);
murmur3_hash(&hasher.bytes, seed)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_murmur3_basic() {
let hash = murmur3_hash(b"test", 0);
assert!(hash > 0);
}
#[test]
fn test_xxhash_basic() {
let hash = xxhash(b"test", 0);
assert!(hash > 0);
}
#[test]
fn test_hash_value_basic() {
let hash = hash_value(&42u64, 0);
assert!(hash > 0);
}
}