use core::hash::{BuildHasherDefault, Hasher};
#[cfg(feature = "std")]
use crate::sym::Sym;
const MIX: u64 = 0x9E37_79B9_7F4A_7C15;
#[derive(Debug, Default)]
pub struct SymHasher(u64);
impl Hasher for SymHasher {
#[inline]
fn finish(&self) -> u64 {
self.0
}
#[inline]
fn write_u32(&mut self, i: u32) {
self.0 = (self.0 ^ u64::from(i)).wrapping_mul(MIX);
}
#[inline]
fn write(&mut self, bytes: &[u8]) {
let mut h = self.0;
for &b in bytes {
h = (h ^ u64::from(b)).wrapping_mul(MIX);
}
self.0 = h;
}
}
pub type SymBuildHasher = BuildHasherDefault<SymHasher>;
#[cfg(feature = "std")]
pub type SymMap<V> = std::collections::HashMap<Sym, V, SymBuildHasher>;
#[cfg(feature = "std")]
pub type SymSet = std::collections::HashSet<Sym, SymBuildHasher>;
#[cfg_attr(coverage_nightly, coverage(off))]
#[cfg(test)]
mod tests {
use core::hash::Hasher;
use super::{MIX, SymHasher};
#[test]
fn write_u32_accumulates_and_mixes() {
let mut hasher = SymHasher::default();
hasher.write_u32(1);
let first = MIX;
assert_eq!(hasher.finish(), first);
hasher.write_u32(1);
assert_eq!(hasher.finish(), (first ^ 1).wrapping_mul(MIX));
}
#[test]
fn write_accumulates_and_mixes_each_byte() {
let mut hasher = SymHasher::default();
hasher.write(&[0xff, 0x55]);
let first = 0xff_u64.wrapping_mul(MIX);
assert_eq!(hasher.finish(), (first ^ 0x55).wrapping_mul(MIX));
}
}