#![deny(clippy::correctness, clippy::complexity, clippy::perf)]
#![allow(clippy::pedantic, clippy::cast_lossless, clippy::unreadable_literal)]
#![cfg_attr(all(not(test), not(feature = "std")), no_std)]
#![cfg_attr(feature = "specialize", feature(min_specialization))]
#![cfg_attr(feature = "stdsimd", feature(stdsimd))]
#[macro_use]
mod convert;
#[cfg(any(
all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes", not(miri)),
all(any(target_arch = "arm", target_arch = "aarch64"), target_feature = "crypto", not(miri), feature = "stdsimd")
))]
mod aes_hash;
mod fallback_hash;
#[cfg(test)]
mod hash_quality_test;
#[cfg(feature = "std")]
mod hash_map;
#[cfg(feature = "std")]
mod hash_set;
mod operations;
mod random_state;
mod specialize;
#[cfg(any(
all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes", not(miri)),
all(any(target_arch = "arm", target_arch = "aarch64"), target_feature = "crypto", not(miri), feature = "stdsimd")
))]
pub use crate::aes_hash::AHasher;
#[cfg(not(any(
all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes", not(miri)),
all(any(target_arch = "arm", target_arch = "aarch64"), target_feature = "crypto", not(miri), feature = "stdsimd")
)))]
pub use crate::fallback_hash::AHasher;
pub use crate::random_state::RandomState;
pub use crate::specialize::CallHasher;
#[cfg(feature = "std")]
pub use crate::hash_map::AHashMap;
#[cfg(feature = "std")]
pub use crate::hash_set::AHashSet;
use core::hash::BuildHasher;
use core::hash::Hash;
use core::hash::Hasher;
impl Default for AHasher {
#[inline]
fn default() -> AHasher {
RandomState::with_fixed_keys().build_hasher()
}
}
pub(crate) trait BuildHasherExt: BuildHasher {
#[doc(hidden)]
fn hash_as_u64<T: Hash + ?Sized>(&self, value: &T) -> u64;
#[doc(hidden)]
fn hash_as_fixed_length<T: Hash + ?Sized>(&self, value: &T) -> u64;
#[doc(hidden)]
fn hash_as_str<T: Hash + ?Sized>(&self, value: &T) -> u64;
}
impl<B: BuildHasher> BuildHasherExt for B {
#[inline]
#[cfg(feature = "specialize")]
default fn hash_as_u64<T: Hash + ?Sized>(&self, value: &T) -> u64 {
let mut hasher = self.build_hasher();
value.hash(&mut hasher);
hasher.finish()
}
#[inline]
#[cfg(not(feature = "specialize"))]
fn hash_as_u64<T: Hash + ?Sized>(&self, value: &T) -> u64 {
let mut hasher = self.build_hasher();
value.hash(&mut hasher);
hasher.finish()
}
#[inline]
#[cfg(feature = "specialize")]
default fn hash_as_fixed_length<T: Hash + ?Sized>(&self, value: &T) -> u64 {
let mut hasher = self.build_hasher();
value.hash(&mut hasher);
hasher.finish()
}
#[inline]
#[cfg(not(feature = "specialize"))]
fn hash_as_fixed_length<T: Hash + ?Sized>(&self, value: &T) -> u64 {
let mut hasher = self.build_hasher();
value.hash(&mut hasher);
hasher.finish()
}
#[inline]
#[cfg(feature = "specialize")]
default fn hash_as_str<T: Hash + ?Sized>(&self, value: &T) -> u64 {
let mut hasher = self.build_hasher();
value.hash(&mut hasher);
hasher.finish()
}
#[inline]
#[cfg(not(feature = "specialize"))]
fn hash_as_str<T: Hash + ?Sized>(&self, value: &T) -> u64 {
let mut hasher = self.build_hasher();
value.hash(&mut hasher);
hasher.finish()
}
}
#[cfg(feature = "std")]
#[cfg(test)]
mod test {
use crate::convert::Convert;
use crate::*;
use std::collections::HashMap;
use std::hash::Hash;
#[test]
fn test_default_builder() {
use core::hash::BuildHasherDefault;
let mut map = HashMap::<u32, u64, BuildHasherDefault<AHasher>>::default();
map.insert(1, 3);
}
#[test]
fn test_builder() {
let mut map = HashMap::<u32, u64, RandomState>::default();
map.insert(1, 3);
}
#[test]
fn test_conversion() {
let input: &[u8] = b"dddddddd";
let bytes: u64 = as_array!(input, 8).convert();
assert_eq!(bytes, 0x6464646464646464);
}
#[test]
fn test_non_zero() {
let mut hasher1 = AHasher::new_with_keys(0, 0);
let mut hasher2 = AHasher::new_with_keys(0, 0);
"foo".hash(&mut hasher1);
"bar".hash(&mut hasher2);
assert_ne!(hasher1.finish(), 0);
assert_ne!(hasher2.finish(), 0);
assert_ne!(hasher1.finish(), hasher2.finish());
let mut hasher1 = AHasher::new_with_keys(0, 0);
let mut hasher2 = AHasher::new_with_keys(0, 0);
3_u64.hash(&mut hasher1);
4_u64.hash(&mut hasher2);
assert_ne!(hasher1.finish(), 0);
assert_ne!(hasher2.finish(), 0);
assert_ne!(hasher1.finish(), hasher2.finish());
}
#[test]
fn test_non_zero_specialized() {
let hasher_build = RandomState::with_seeds(0,0,0,0);
let h1 = str::get_hash("foo", &hasher_build);
let h2 = str::get_hash("bar", &hasher_build);
assert_ne!(h1, 0);
assert_ne!(h2, 0);
assert_ne!(h1, h2);
let h1 = u64::get_hash(&3_u64, &hasher_build);
let h2 = u64::get_hash(&4_u64, &hasher_build);
assert_ne!(h1, 0);
assert_ne!(h2, 0);
assert_ne!(h1, h2);
}
#[test]
fn test_ahasher_construction() {
let _ = AHasher::new_with_keys(1234, 5678);
}
}