1#[cfg(any(feature = "wyhash-hash", feature = "xxh3-hash"))]
4use core::hash::BuildHasher;
5
6#[cfg(all(
8 feature = "random-state-hash",
9 any(feature = "wyhash-hash", feature = "xxh3-hash")
10))]
11compile_error!(
12 "Features 'random-state-hash' and ('wyhash-hash' or 'xxh3-hash') are mutually exclusive"
13);
14#[cfg(all(feature = "wyhash-hash", feature = "xxh3-hash"))]
15compile_error!("Features 'wyhash-hash' and 'xxh3-hash' are mutually exclusive");
16#[cfg(all(
17 not(feature = "random-state-hash"),
18 not(feature = "wyhash-hash"),
19 not(feature = "xxh3-hash")
20))]
21compile_error!(
22 "No default hash feature selected. Enable exactly one of: 'wyhash-hash' (default), 'random-state-hash', or 'xxh3-hash'"
23);
24
25#[cfg(feature = "random-state-hash")]
27pub type DefaultHashBuilder = std::collections::hash_map::RandomState;
28
29#[cfg(feature = "wyhash-hash")]
30pub type DefaultHashBuilder = WyHashRandomState;
31
32#[cfg(feature = "xxh3-hash")]
33pub type DefaultHashBuilder = Xxh3RandomState;
34
35#[cfg(feature = "wyhash-hash")]
37pub const HASH_NAME: &str = "wyhash-hash";
38#[cfg(feature = "random-state-hash")]
39pub const HASH_NAME: &str = "random-state-hash";
40#[cfg(feature = "xxh3-hash")]
41pub const HASH_NAME: &str = "xxh3-hash";
42
43#[cfg(any(feature = "wyhash-hash", feature = "xxh3-hash"))]
45mod seed {
46 use std::cell::Cell;
47 use std::time::{SystemTime, UNIX_EPOCH};
48
49 thread_local! {
50 static KEY: Cell<u64> = Cell::new(init_key());
51 }
52
53 fn init_key() -> u64 {
54 let mut buf = [0u8; 8];
55 if getrandom::getrandom(&mut buf).is_ok() {
56 u64::from_le_bytes(buf)
57 } else {
58 let now = SystemTime::now()
60 .duration_since(UNIX_EPOCH)
61 .unwrap_or_default();
62 let t: u128 = now.as_nanos();
63 let lo = t as u64;
64 let hi = (t >> 64) as u64;
65 let mut k = lo ^ hi.rotate_left(29) ^ 0x9e37_79b9_7f4a_7c15u64;
66 k ^= k.wrapping_mul(0x9e37_79b9_7f4a_7c15u64);
68 k
69 }
70 }
71
72 #[inline]
73 pub fn next_seed() -> u64 {
74 KEY.with(|key| {
75 let k = key.get();
76 key.set(k.wrapping_add(1));
77 k
78 })
79 }
80}
81
82#[cfg(feature = "wyhash-hash")]
84#[derive(Clone)]
85pub struct WyHashRandomState {
86 builder: wyhash::v1::WyHasherBuilder,
87}
88
89#[cfg(feature = "wyhash-hash")]
90impl Default for WyHashRandomState {
91 fn default() -> Self {
92 let seed = seed::next_seed();
93 Self {
94 builder: wyhash::v1::WyHasherBuilder::new(seed),
95 }
96 }
97}
98
99#[cfg(feature = "wyhash-hash")]
100impl BuildHasher for WyHashRandomState {
101 type Hasher = <wyhash::v1::WyHasherBuilder as BuildHasher>::Hasher;
102 #[inline]
103 fn build_hasher(&self) -> Self::Hasher {
104 self.builder.build_hasher()
105 }
106}
107
108#[cfg(feature = "xxh3-hash")]
110#[derive(Clone)]
111pub struct Xxh3RandomState {
112 builder: xxhash_rust::xxh3::Xxh3Builder,
113}
114
115#[cfg(feature = "xxh3-hash")]
116impl Default for Xxh3RandomState {
117 fn default() -> Self {
118 let seed = seed::next_seed();
119 let builder = xxhash_rust::xxh3::Xxh3Builder::new().with_seed(seed);
120 Self { builder }
121 }
122}
123
124#[cfg(feature = "xxh3-hash")]
125impl BuildHasher for Xxh3RandomState {
126 type Hasher = <xxhash_rust::xxh3::Xxh3Builder as BuildHasher>::Hasher;
127 #[inline]
128 fn build_hasher(&self) -> Self::Hasher {
129 self.builder.build_hasher()
130 }
131}