use core::hash::BuildHasher;
use core::hash::Hash;
use core::hash::Hasher;
#[ cfg(not(feature = "std" ))]
extern crate alloc;
#[ cfg(feature = "std" )]
extern crate std as alloc;
#[ cfg(feature = "specialize" )]
use crate ::BuildHasherExt;
#[ cfg(feature = "specialize" )]
use alloc::string::String;
#[ cfg(feature = "specialize" )]
use alloc::vec::Vec;
/// Provides a way to get an optimized hasher for a given data type.
/// Rather than using a Hasher generically which can hash any value, this provides a way to get a specialized hash
/// for a specific type. So this may be faster for primitive types.
pub (crate ) trait CallHasher {
fn get_hash<H: Hash + ?Sized, B: BuildHasher>(value: &H, build_hasher: &B) -> u64;
}
#[ cfg(not(feature = "specialize" ))]
impl <T> CallHasher for T
where
T: Hash + ?Sized,
{
#[ inline]
fn get_hash<H: Hash + ?Sized, B: BuildHasher>(value: &H, build_hasher: &B) -> u64 {
let mut hasher = build_hasher.build_hasher();
value.hash(&mut hasher);
hasher.finish()
}
}
#[ cfg(feature = "specialize" )]
impl <T> CallHasher for T
where
T: Hash + ?Sized,
{
#[ inline]
default fn get_hash<H: Hash + ?Sized, B: BuildHasher>(value: &H, build_hasher: &B) -> u64 {
let mut hasher = build_hasher.build_hasher();
value.hash(&mut hasher);
hasher.finish()
}
}
macro_rules! call_hasher_impl {
($typ:ty) => {
#[ cfg(feature = "specialize" )]
impl CallHasher for $typ {
#[ inline]
fn get_hash<H: Hash + ?Sized, B: BuildHasher>(value: &H, build_hasher: &B) -> u64 {
build_hasher.hash_as_u64(value)
}
}
};
}
call_hasher_impl!(u8);
call_hasher_impl!(u16);
call_hasher_impl!(u32);
call_hasher_impl!(u64);
call_hasher_impl!(i8);
call_hasher_impl!(i16);
call_hasher_impl!(i32);
call_hasher_impl!(i64);
#[ cfg(feature = "specialize" )]
impl CallHasher for u128 {
#[ inline]
fn get_hash<H: Hash + ?Sized, B: BuildHasher>(value: &H, build_hasher: &B) -> u64 {
build_hasher.hash_as_fixed_length(value)
}
}
#[ cfg(feature = "specialize" )]
impl CallHasher for i128 {
#[ inline]
fn get_hash<H: Hash + ?Sized, B: BuildHasher>(value: &H, build_hasher: &B) -> u64 {
build_hasher.hash_as_fixed_length(value)
}
}
#[ cfg(feature = "specialize" )]
impl CallHasher for usize {
#[ inline]
fn get_hash<H: Hash + ?Sized, B: BuildHasher>(value: &H, build_hasher: &B) -> u64 {
build_hasher.hash_as_fixed_length(value)
}
}
#[ cfg(feature = "specialize" )]
impl CallHasher for isize {
#[ inline]
fn get_hash<H: Hash + ?Sized, B: BuildHasher>(value: &H, build_hasher: &B) -> u64 {
build_hasher.hash_as_fixed_length(value)
}
}
#[ cfg(feature = "specialize" )]
impl CallHasher for [u8] {
#[ inline]
fn get_hash<H: Hash + ?Sized, B: BuildHasher>(value: &H, build_hasher: &B) -> u64 {
build_hasher.hash_as_str(value)
}
}
#[ cfg(feature = "specialize" )]
impl CallHasher for Vec<u8> {
#[ inline]
fn get_hash<H: Hash + ?Sized, B: BuildHasher>(value: &H, build_hasher: &B) -> u64 {
build_hasher.hash_as_str(value)
}
}
#[ cfg(feature = "specialize" )]
impl CallHasher for str {
#[ inline]
fn get_hash<H: Hash + ?Sized, B: BuildHasher>(value: &H, build_hasher: &B) -> u64 {
build_hasher.hash_as_str(value)
}
}
#[ cfg(all(feature = "specialize" ))]
impl CallHasher for String {
#[ inline]
fn get_hash<H: Hash + ?Sized, B: BuildHasher>(value: &H, build_hasher: &B) -> u64 {
build_hasher.hash_as_str(value)
}
}
#[ cfg(test)]
mod test {
use super ::*;
use crate ::*;
#[ test]
#[ cfg(feature = "specialize" )]
pub fn test_specialized_invoked() {
let build_hasher = RandomState::with_seeds(1 , 2 , 3 , 4 );
let shortened = u64::get_hash(&0 , &build_hasher);
let mut hasher = AHasher::new_with_keys(1 , 2 );
0 _u64.hash(&mut hasher);
assert_ne!(hasher.finish(), shortened);
}
/// Tests that some non-trivial transformation takes place.
#[ test]
pub fn test_input_processed() {
let build_hasher = RandomState::with_seeds(2 , 2 , 2 , 2 );
assert_ne!(0 , u64::get_hash(&0 , &build_hasher));
assert_ne!(1 , u64::get_hash(&0 , &build_hasher));
assert_ne!(2 , u64::get_hash(&0 , &build_hasher));
assert_ne!(3 , u64::get_hash(&0 , &build_hasher));
assert_ne!(4 , u64::get_hash(&0 , &build_hasher));
assert_ne!(5 , u64::get_hash(&0 , &build_hasher));
assert_ne!(0 , u64::get_hash(&1 , &build_hasher));
assert_ne!(1 , u64::get_hash(&1 , &build_hasher));
assert_ne!(2 , u64::get_hash(&1 , &build_hasher));
assert_ne!(3 , u64::get_hash(&1 , &build_hasher));
assert_ne!(4 , u64::get_hash(&1 , &build_hasher));
assert_ne!(5 , u64::get_hash(&1 , &build_hasher));
let xored = u64::get_hash(&0 , &build_hasher) ^ u64::get_hash(&e='color: green'>1 , &build_hasher);
assert_ne!(0 , xored);
assert_ne!(1 , xored);
assert_ne!(2 , xored);
assert_ne!(3 , xored);
assert_ne!(4 , xored);
assert_ne!(5 , xored);
}
#[ test]
pub fn test_ref_independent() {
let build_hasher = RandomState::with_seeds(1 , 2 , 3 , 4 );
assert_eq!(u8::get_hash(&&1 , &build_hasher), u8::get_hash(&1 , &build_hasher));
assert_eq!(u16::get_hash(&&2 , &build_hasher), u16::get_hash(&2 , &build_hasher));
assert_eq!(u32::get_hash(&&3 , &build_hasher), u32::get_hash(&3 , &build_hasher));
assert_eq!(u64::get_hash(&&4 , &build_hasher), u64::get_hash(&4 , &build_hasher));
assert_eq!(u128::get_hash(&&5 , &build_hasher), u128::get_hash(&5 , &build_hasher));
assert_eq!(
str::get_hash(&"test" , &build_hasher),
str::get_hash("test" , &build_hasher)
);
assert_eq!(
str::get_hash(&"test" , &build_hasher),
String::get_hash(&"test" .to_string(), &build_hasher)
);
#[ cfg(feature = "specialize" )]
assert_eq!(
str::get_hash(&"test" , &build_hasher),
<[u8]>::get_hash("test" .as_bytes(), &build_hasher)
);
let build_hasher = RandomState::with_seeds(10 , 20 , 30 , 40 );
assert_eq!(u8::get_hash(&&&1 , &build_hasher), u8::get_hash(&='color: green'>1 , &build_hasher));
assert_eq!(u16::get_hash(&&&2 , &build_hasher), u16::get_hash(&le='color: green'>2 , &build_hasher));
assert_eq!(u32::get_hash(&&&3 , &build_hasher), u32::get_hash(&le='color: green'>3 , &build_hasher));
assert_eq!(u64::get_hash(&&&4 , &build_hasher), u64::get_hash(&le='color: green'>4 , &build_hasher));
assert_eq!(u128::get_hash(&&&5 , &build_hasher), u128::get_hash(&tyle='color: green'>5 , &build_hasher));
assert_eq!(
str::get_hash(&&"test" , &build_hasher),
str::get_hash("test" , &build_hasher)
);
assert_eq!(
str::get_hash(&&"test" , &build_hasher),
String::get_hash(&"test" .to_string(), &build_hasher)
);
#[ cfg(feature = "specialize" )]
assert_eq!(
str::get_hash(&&"test" , &build_hasher),
<[u8]>::get_hash(&"test" .to_string().into_bytes(), &build_hasher)
);
}
}
Messung V0.5 in Prozent C=94 H=99 G=96
¤ Dauer der Verarbeitung: 0.12 Sekunden
(vorverarbeitet am 2026-06-20)
¤
*© Formatika GbR, Deutschland