use std::hash::{BuildHasherDefault, Hasher};
const MULTIPLIER: u64 = 0x9E37_79B9_7F4A_7C15;
const FOLD: u32 = 29;
#[derive(Debug, Clone, Copy, Default)]
pub struct IdentityHasher {
state: u64,
}
impl IdentityHasher {
fn absorb(&mut self, value: u64) {
self.state = (self.state ^ value).wrapping_mul(MULTIPLIER);
self.state ^= self.state >> FOLD;
}
}
impl Hasher for IdentityHasher {
fn finish(&self) -> u64 {
self.state
}
fn write(&mut self, bytes: &[u8]) {
let (chunks, remainder) = bytes.as_chunks::<8>();
for chunk in chunks {
self.absorb(u64::from_le_bytes(*chunk));
}
if !remainder.is_empty() {
let mut word = [0u8; 8];
match word.get_mut(..remainder.len()) {
Some(head) => head.copy_from_slice(remainder),
None => return,
}
self.absorb(u64::from_le_bytes(word));
}
}
fn write_u8(&mut self, value: u8) {
self.absorb(u64::from(value));
}
fn write_u16(&mut self, value: u16) {
self.absorb(u64::from(value));
}
fn write_u32(&mut self, value: u32) {
self.absorb(u64::from(value));
}
fn write_u64(&mut self, value: u64) {
self.absorb(value);
}
fn write_usize(&mut self, value: usize) {
self.absorb(value as u64);
}
}
pub type IdentityBuildHasher = BuildHasherDefault<IdentityHasher>;
pub type IdentityHashMap<K, V> = std::collections::HashMap<K, V, IdentityBuildHasher>;
pub type IdentityHashSet<K> = std::collections::HashSet<K, IdentityBuildHasher>;
#[cfg(test)]
#[path = "mix_tests.rs"]
mod tests;