1#![deny(clippy::correctness, clippy::complexity, clippy::perf)]
30#![allow(clippy::pedantic, clippy::cast_lossless, clippy::unreadable_literal)]
31#![cfg_attr(all(not(test), not(feature = "std")), no_std)]
32#![cfg_attr(feature = "specialize", feature(min_specialization))]
33#![cfg_attr(feature = "stdsimd", feature(stdsimd))]
34
35#[macro_use]
36mod convert;
37
38#[cfg(any(
39 all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes", not(miri)),
40 all(any(target_arch = "arm", target_arch = "aarch64"), target_feature = "crypto", not(miri), feature = "stdsimd")
41))]
42mod aes_hash;
43mod fallback_hash;
44#[cfg(test)]
45mod hash_quality_test;
46
47#[cfg(feature = "std")]
48mod hash_map;
49#[cfg(feature = "std")]
50mod hash_set;
51mod operations;
52mod random_state;
53mod specialize;
54
55#[cfg(any(
56 all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes", not(miri)),
57 all(any(target_arch = "arm", target_arch = "aarch64"), target_feature = "crypto", not(miri), feature = "stdsimd")
58))]
59pub use crate::aes_hash::AHasher;
60
61#[cfg(not(any(
62 all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes", not(miri)),
63 all(any(target_arch = "arm", target_arch = "aarch64"), target_feature = "crypto", not(miri), feature = "stdsimd")
64)))]
65pub use crate::fallback_hash::AHasher;
66pub use crate::random_state::RandomState;
67
68pub use crate::specialize::CallHasher;
69
70#[cfg(feature = "std")]
71pub use crate::hash_map::AHashMap;
72#[cfg(feature = "std")]
73pub use crate::hash_set::AHashSet;
74use core::hash::BuildHasher;
75use core::hash::Hash;
76use core::hash::Hasher;
77
78impl Default for AHasher {
100 #[inline]
124 fn default() -> AHasher {
125 RandomState::with_fixed_keys().build_hasher()
126 }
127}
128
129pub(crate) trait BuildHasherExt: BuildHasher {
131 #[doc(hidden)]
132 fn hash_as_u64<T: Hash + ?Sized>(&self, value: &T) -> u64;
133
134 #[doc(hidden)]
135 fn hash_as_fixed_length<T: Hash + ?Sized>(&self, value: &T) -> u64;
136
137 #[doc(hidden)]
138 fn hash_as_str<T: Hash + ?Sized>(&self, value: &T) -> u64;
139}
140
141impl<B: BuildHasher> BuildHasherExt for B {
142 #[inline]
143 #[cfg(feature = "specialize")]
144 default fn hash_as_u64<T: Hash + ?Sized>(&self, value: &T) -> u64 {
145 let mut hasher = self.build_hasher();
146 value.hash(&mut hasher);
147 hasher.finish()
148 }
149 #[inline]
150 #[cfg(not(feature = "specialize"))]
151 fn hash_as_u64<T: Hash + ?Sized>(&self, value: &T) -> u64 {
152 let mut hasher = self.build_hasher();
153 value.hash(&mut hasher);
154 hasher.finish()
155 }
156 #[inline]
157 #[cfg(feature = "specialize")]
158 default fn hash_as_fixed_length<T: Hash + ?Sized>(&self, value: &T) -> u64 {
159 let mut hasher = self.build_hasher();
160 value.hash(&mut hasher);
161 hasher.finish()
162 }
163 #[inline]
164 #[cfg(not(feature = "specialize"))]
165 fn hash_as_fixed_length<T: Hash + ?Sized>(&self, value: &T) -> u64 {
166 let mut hasher = self.build_hasher();
167 value.hash(&mut hasher);
168 hasher.finish()
169 }
170 #[inline]
171 #[cfg(feature = "specialize")]
172 default fn hash_as_str<T: Hash + ?Sized>(&self, value: &T) -> u64 {
173 let mut hasher = self.build_hasher();
174 value.hash(&mut hasher);
175 hasher.finish()
176 }
177 #[inline]
178 #[cfg(not(feature = "specialize"))]
179 fn hash_as_str<T: Hash + ?Sized>(&self, value: &T) -> u64 {
180 let mut hasher = self.build_hasher();
181 value.hash(&mut hasher);
182 hasher.finish()
183 }
184}
185
186#[cfg(feature = "std")]
194#[cfg(test)]
195mod test {
196 use crate::convert::Convert;
197 use crate::*;
198 use std::collections::HashMap;
199 use std::hash::Hash;
200
201 #[test]
202 fn test_default_builder() {
203 use core::hash::BuildHasherDefault;
204
205 let mut map = HashMap::<u32, u64, BuildHasherDefault<AHasher>>::default();
206 map.insert(1, 3);
207 }
208
209 #[test]
210 fn test_builder() {
211 let mut map = HashMap::<u32, u64, RandomState>::default();
212 map.insert(1, 3);
213 }
214
215 #[test]
216 fn test_conversion() {
217 let input: &[u8] = b"dddddddd";
218 let bytes: u64 = as_array!(input, 8).convert();
219 assert_eq!(bytes, 0x6464646464646464);
220 }
221
222
223 #[test]
224 fn test_non_zero() {
225 let mut hasher1 = AHasher::new_with_keys(0, 0);
226 let mut hasher2 = AHasher::new_with_keys(0, 0);
227 "foo".hash(&mut hasher1);
228 "bar".hash(&mut hasher2);
229 assert_ne!(hasher1.finish(), 0);
230 assert_ne!(hasher2.finish(), 0);
231 assert_ne!(hasher1.finish(), hasher2.finish());
232
233 let mut hasher1 = AHasher::new_with_keys(0, 0);
234 let mut hasher2 = AHasher::new_with_keys(0, 0);
235 3_u64.hash(&mut hasher1);
236 4_u64.hash(&mut hasher2);
237 assert_ne!(hasher1.finish(), 0);
238 assert_ne!(hasher2.finish(), 0);
239 assert_ne!(hasher1.finish(), hasher2.finish());
240 }
241
242 #[test]
243 fn test_non_zero_specialized() {
244 let hasher_build = RandomState::with_seeds(0,0,0,0);
245
246 let h1 = str::get_hash("foo", &hasher_build);
247 let h2 = str::get_hash("bar", &hasher_build);
248 assert_ne!(h1, 0);
249 assert_ne!(h2, 0);
250 assert_ne!(h1, h2);
251
252 let h1 = u64::get_hash(&3_u64, &hasher_build);
253 let h2 = u64::get_hash(&4_u64, &hasher_build);
254 assert_ne!(h1, 0);
255 assert_ne!(h2, 0);
256 assert_ne!(h1, h2);
257 }
258
259 #[test]
260 fn test_ahasher_construction() {
261 let _ = AHasher::new_with_keys(1234, 5678);
262 }
263}