#[cfg(feature = "specialize")]
use crate::HasherExt;
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 alloc::string::String;
#[cfg(feature = "specialize")]
use alloc::vec::Vec;
pub trait CallHasher {
fn get_hash<H: Hasher>(value: &Self, hasher: H) -> u64;
}
#[cfg(not(feature = "specialize"))]
impl<T> CallHasher for T
where
T: Hash + ?Sized,
{
#[inline]
fn get_hash<H: Hasher>(value: &T, mut hasher: H) -> u64 {
value.hash(&mut hasher);
hasher.finish()
}
}
#[cfg(feature = "specialize")]
impl<T> CallHasher for T
where
T: Hash + ?Sized,
{
#[inline]
default fn get_hash<H: Hasher>(value: &T, mut hasher: H) -> u64 {
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: Hasher>(value: &$typ, hasher: H) -> u64 {
hasher.hash_u64(*value as u64)
}
}
#[cfg(feature = "specialize")]
impl CallHasher for &$typ {
#[inline]
fn get_hash<H: Hasher>(value: &&$typ, hasher: H) -> u64 {
hasher.hash_u64(**value as u64)
}
}
#[cfg(feature = "specialize")]
impl CallHasher for &&$typ {
#[inline]
fn get_hash<H: Hasher>(value: &&&$typ, hasher: H) -> u64 {
hasher.hash_u64(***value as u64)
}
}
};
}
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: Hasher>(value: &u128, mut hasher: H) -> u64 {
hasher.write_u128(*value);
hasher.short_finish()
}
}
#[cfg(feature = "specialize")]
impl CallHasher for &u128 {
#[inline]
fn get_hash<H: Hasher>(value: &&u128, mut hasher: H) -> u64 {
hasher.write_u128(**value);
hasher.short_finish()
}
}
#[cfg(feature = "specialize")]
impl CallHasher for &&u128 {
#[inline]
fn get_hash<H: Hasher>(value: &&&u128, mut hasher: H) -> u64 {
hasher.write_u128(***value);
hasher.short_finish()
}
}
#[cfg(feature = "specialize")]
impl CallHasher for i128 {
#[inline]
fn get_hash<H: Hasher>(value: &i128, mut hasher: H) -> u64 {
hasher.write_u128(*value as u128);
hasher.short_finish()
}
}
#[cfg(feature = "specialize")]
impl CallHasher for &i128 {
#[inline]
fn get_hash<H: Hasher>(value: &&i128, mut hasher: H) -> u64 {
hasher.write_u128(**value as u128);
hasher.short_finish()
}
}
#[cfg(feature = "specialize")]
impl CallHasher for &&i128 {
#[inline]
fn get_hash<H: Hasher>(value: &&&i128, mut hasher: H) -> u64 {
hasher.write_u128(***value as u128);
hasher.short_finish()
}
}
#[cfg(feature = "specialize")]
impl CallHasher for [u8] {
#[inline]
fn get_hash<H: Hasher>(value: &Self, mut hasher: H) -> u64 {
hasher.write(value);
hasher.finish()
}
}
#[cfg(feature = "specialize")]
impl CallHasher for &[u8] {
#[inline]
fn get_hash<H: Hasher>(value: &Self, mut hasher: H) -> u64 {
hasher.write(*value);
hasher.finish()
}
}
#[cfg(feature = "specialize")]
impl CallHasher for &&[u8] {
#[inline]
fn get_hash<H: Hasher>(value: &Self, mut hasher: H) -> u64 {
hasher.write(**value);
hasher.finish()
}
}
#[cfg(feature = "specialize")]
impl CallHasher for Vec<u8> {
#[inline]
fn get_hash<H: Hasher>(value: &Self, mut hasher: H) -> u64 {
hasher.write(value);
hasher.finish()
}
}
#[cfg(feature = "specialize")]
impl CallHasher for &Vec<u8> {
#[inline]
fn get_hash<H: Hasher>(value: &Self, mut hasher: H) -> u64 {
hasher.write(*value);
hasher.finish()
}
}
#[cfg(feature = "specialize")]
impl CallHasher for &&Vec<u8> {
#[inline]
fn get_hash<H: Hasher>(value: &Self, mut hasher: H) -> u64 {
hasher.write(**value);
hasher.finish()
}
}
#[cfg(feature = "specialize")]
impl CallHasher for str {
#[inline]
fn get_hash<H: Hasher>(value: &Self, mut hasher: H) -> u64 {
hasher.write(value.as_bytes());
hasher.finish()
}
}
#[cfg(feature = "specialize")]
impl CallHasher for &str {
#[inline]
fn get_hash<H: Hasher>(value: &Self, mut hasher: H) -> u64 {
hasher.write(value.as_bytes());
hasher.finish()
}
}
#[cfg(feature = "specialize")]
impl CallHasher for &&str {
#[inline]
fn get_hash<H: Hasher>(value: &Self, mut hasher: H) -> u64 {
hasher.write(value.as_bytes());
hasher.finish()
}
}
#[cfg(feature = "specialize")]
impl CallHasher for &&&str {
#[inline]
fn get_hash<H: Hasher>(value: &Self, mut hasher: H) -> u64 {
hasher.write(value.as_bytes());
hasher.finish()
}
}
#[cfg(all(feature = "specialize"))]
impl CallHasher for String {
#[inline]
fn get_hash<H: Hasher>(value: &Self, mut hasher: H) -> u64 {
hasher.write(value.as_bytes());
hasher.finish()
}
}
#[cfg(all(feature = "specialize"))]
impl CallHasher for &String {
#[inline]
fn get_hash<H: Hasher>(value: &Self, mut hasher: H) -> u64 {
hasher.write(value.as_bytes());
hasher.finish()
}
}
#[cfg(all(feature = "specialize"))]
impl CallHasher for &&String {
#[inline]
fn get_hash<H: Hasher>(value: &Self, mut hasher: H) -> u64 {
hasher.write(value.as_bytes());
hasher.finish()
}
}
#[cfg(all(feature = "specialize"))]
impl CallHasher for &&&String {
#[inline]
fn get_hash<H: Hasher>(value: &Self, mut hasher: H) -> u64 {
hasher.write(value.as_bytes());
hasher.finish()
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::*;
#[test]
#[cfg(feature = "specialize")]
pub fn test_specialized_invoked() {
let shortened = u64::get_hash(&0, AHasher::new_with_keys(1, 2));
let mut hasher = AHasher::new_with_keys(1, 2);
0_u64.hash(&mut hasher);
assert_ne!(hasher.finish(), shortened);
}
#[test]
pub fn test_input_processed() {
let hasher = || AHasher::new_with_keys(3, 2);
assert_ne!(0, u64::get_hash(&0, hasher()));
assert_ne!(1, u64::get_hash(&0, hasher()));
assert_ne!(2, u64::get_hash(&0, hasher()));
assert_ne!(3, u64::get_hash(&0, hasher()));
assert_ne!(4, u64::get_hash(&0, hasher()));
assert_ne!(5, u64::get_hash(&0, hasher()));
assert_ne!(0, u64::get_hash(&1, hasher()));
assert_ne!(1, u64::get_hash(&1, hasher()));
assert_ne!(2, u64::get_hash(&1, hasher()));
assert_ne!(3, u64::get_hash(&1, hasher()));
assert_ne!(4, u64::get_hash(&1, hasher()));
assert_ne!(5, u64::get_hash(&1, hasher()));
let xored = u64::get_hash(&0, hasher()) ^ u64::get_hash(&1, 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 hasher = || AHasher::new_with_keys(3, 2);
assert_eq!(<&u8>::get_hash(&&1, hasher()), u8::get_hash(&1, hasher()));
assert_eq!(<&u16>::get_hash(&&2, hasher()), u16::get_hash(&2, hasher()));
assert_eq!(<&u32>::get_hash(&&3, hasher()), u32::get_hash(&3, hasher()));
assert_eq!(<&u64>::get_hash(&&4, hasher()), u64::get_hash(&4, hasher()));
assert_eq!(<&u128>::get_hash(&&5, hasher()), u128::get_hash(&5, hasher()));
assert_eq!(<&str>::get_hash(&"test", hasher()), str::get_hash("test", hasher()));
assert_eq!(<&str>::get_hash(&"test", hasher()), String::get_hash(&"test".to_string(), hasher()));
#[cfg(feature = "specialize")]
assert_eq!(<&str>::get_hash(&"test", hasher()), <[u8]>::get_hash("test".as_bytes(), hasher()));
let hasher = || AHasher::new_with_keys(3, 2);
assert_eq!(<&&u8>::get_hash(&&&1, hasher()), u8::get_hash(&1, hasher()));
assert_eq!(<&&u16>::get_hash(&&&2, hasher()), u16::get_hash(&2, hasher()));
assert_eq!(<&&u32>::get_hash(&&&3, hasher()), u32::get_hash(&3, hasher()));
assert_eq!(<&&u64>::get_hash(&&&4, hasher()), u64::get_hash(&4, hasher()));
assert_eq!(<&&u128>::get_hash(&&&5, hasher()), u128::get_hash(&5, hasher()));
assert_eq!(<&&str>::get_hash(&&"test", hasher()), str::get_hash("test",hasher()));
assert_eq!(<&&str>::get_hash(&&"test", hasher()), String::get_hash(&"test".to_string(), hasher()));
#[cfg(feature = "specialize")]
assert_eq!(<&&str>::get_hash(&&"test", hasher()), <[u8]>::get_hash(&"test".to_string().into_bytes(), hasher()));
}
}