#[cfg(any(feature = "wyhash-hash", feature = "xxh3-hash"))]
use core::hash::BuildHasher;
#[cfg(all(
feature = "random-state-hash",
any(feature = "wyhash-hash", feature = "xxh3-hash")
))]
compile_error!(
"Features 'random-state-hash' and ('wyhash-hash' or 'xxh3-hash') are mutually exclusive"
);
#[cfg(all(feature = "wyhash-hash", feature = "xxh3-hash"))]
compile_error!("Features 'wyhash-hash' and 'xxh3-hash' are mutually exclusive");
#[cfg(all(
not(feature = "random-state-hash"),
not(feature = "wyhash-hash"),
not(feature = "xxh3-hash")
))]
compile_error!(
"No default hash feature selected. Enable exactly one of: 'wyhash-hash' (default), 'random-state-hash', or 'xxh3-hash'"
);
#[cfg(feature = "random-state-hash")]
pub type DefaultHashBuilder = std::collections::hash_map::RandomState;
#[cfg(feature = "wyhash-hash")]
pub type DefaultHashBuilder = WyHashRandomState;
#[cfg(feature = "xxh3-hash")]
pub type DefaultHashBuilder = Xxh3RandomState;
#[cfg(feature = "wyhash-hash")]
pub const HASH_NAME: &str = "wyhash-hash";
#[cfg(feature = "random-state-hash")]
pub const HASH_NAME: &str = "random-state-hash";
#[cfg(feature = "xxh3-hash")]
pub const HASH_NAME: &str = "xxh3-hash";
#[cfg(any(feature = "wyhash-hash", feature = "xxh3-hash"))]
mod seed {
use std::cell::Cell;
use std::time::{SystemTime, UNIX_EPOCH};
thread_local! {
static KEY: Cell<u64> = Cell::new(init_key());
}
fn init_key() -> u64 {
let mut buf = [0u8; 8];
if getrandom::getrandom(&mut buf).is_ok() {
u64::from_le_bytes(buf)
} else {
let now = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap_or_default();
let t: u128 = now.as_nanos();
let lo = t as u64;
let hi = (t >> 64) as u64;
let mut k = lo ^ hi.rotate_left(29) ^ 0x9e37_79b9_7f4a_7c15u64;
k ^= k.wrapping_mul(0x9e37_79b9_7f4a_7c15u64);
k
}
}
#[inline]
pub fn next_seed() -> u64 {
KEY.with(|key| {
let k = key.get();
key.set(k.wrapping_add(1));
k
})
}
}
#[cfg(feature = "wyhash-hash")]
#[derive(Clone)]
pub struct WyHashRandomState {
builder: wyhash::v1::WyHasherBuilder,
}
#[cfg(feature = "wyhash-hash")]
impl Default for WyHashRandomState {
fn default() -> Self {
let seed = seed::next_seed();
Self {
builder: wyhash::v1::WyHasherBuilder::new(seed),
}
}
}
#[cfg(feature = "wyhash-hash")]
impl BuildHasher for WyHashRandomState {
type Hasher = <wyhash::v1::WyHasherBuilder as BuildHasher>::Hasher;
#[inline]
fn build_hasher(&self) -> Self::Hasher {
self.builder.build_hasher()
}
}
#[cfg(feature = "xxh3-hash")]
#[derive(Clone)]
pub struct Xxh3RandomState {
builder: xxhash_rust::xxh3::Xxh3Builder,
}
#[cfg(feature = "xxh3-hash")]
impl Default for Xxh3RandomState {
fn default() -> Self {
let seed = seed::next_seed();
let builder = xxhash_rust::xxh3::Xxh3Builder::new().with_seed(seed);
Self { builder }
}
}
#[cfg(feature = "xxh3-hash")]
impl BuildHasher for Xxh3RandomState {
type Hasher = <xxhash_rust::xxh3::Xxh3Builder as BuildHasher>::Hasher;
#[inline]
fn build_hasher(&self) -> Self::Hasher {
self.builder.build_hasher()
}
}