use core::hash::{BuildHasher, Hasher};
#[allow(dead_code)]
pub(crate) const HASH_VERSION: u32 = 1;
#[inline]
pub(crate) const fn mix64(mut z: u64) -> u64 {
z = (z ^ (z >> 30)).wrapping_mul(0xbf58_476d_1ce4_e5b9);
z = (z ^ (z >> 27)).wrapping_mul(0x94d0_49bb_1331_11eb);
z ^ (z >> 31)
}
#[inline]
pub(crate) const fn combine(h: u64, v: u64) -> u64 {
mix64(h.rotate_left(23) ^ v.wrapping_add(0x9e37_79b9_7f4a_7c15))
}
pub(crate) fn bytes(seed: u64, b: &[u8]) -> u64 {
let mut h = combine(seed, b.len() as u64);
for chunk in b.chunks(8) {
let mut w = [0u8; 8];
w[..chunk.len()].copy_from_slice(chunk);
h = combine(h, u64::from_le_bytes(w));
}
h
}
#[derive(Default, Clone, Copy, Debug)]
pub(crate) struct IdHasher(u64);
impl Hasher for IdHasher {
#[inline]
fn finish(&self) -> u64 {
mix64(self.0)
}
#[inline]
fn write(&mut self, bytes: &[u8]) {
self.0 = self::bytes(self.0, bytes);
}
#[inline]
fn write_u32(&mut self, i: u32) {
self.0 = combine(self.0, u64::from(i));
}
#[inline]
fn write_u64(&mut self, i: u64) {
self.0 = combine(self.0, i);
}
#[inline]
fn write_usize(&mut self, i: usize) {
self.0 = combine(self.0, i as u64);
}
}
#[derive(Default, Clone, Copy, Debug)]
pub(crate) struct IdBuild;
impl BuildHasher for IdBuild {
type Hasher = IdHasher;
#[inline]
fn build_hasher(&self) -> IdHasher {
IdHasher(0)
}
}
pub(crate) type IdMap<K, V> = std::collections::HashMap<K, V, IdBuild>;