diff --git a/src/specialize.rs b/src/specialize.rs index a7bf1f9..6086c23 100644 --- a/src/specialize.rs +++ b/src/specialize.rs @@ -8,6 +8,10 @@ extern crate alloc; #[cfg(feature = "std")] extern crate std as alloc; +#[cfg(specialize)] +use alloc::ffi::{OsStr, OsString}; +#[cfg(specialize)] +use alloc::path::{Path, PathBuf}; #[cfg(specialize)] use alloc::string::String; #[cfg(specialize)] @@ -48,6 +52,15 @@ where macro_rules! call_hasher_impl_u64 { ($typ:ty) => { + call_hasher_impl_u64!(@internal $typ); + call_hasher_impl_u64!(@internal &$typ); + call_hasher_impl_u64!(@internal &&$typ); + call_hasher_impl_u64!(@internal &&&$typ); + call_hasher_impl_u64!(@internal &&&&$typ); + call_hasher_impl_u64!(@internal &&&&&$typ); + }; + + (@internal $typ:ty) => { #[cfg(specialize)] impl CallHasher for $typ { #[inline] @@ -65,17 +78,18 @@ call_hasher_impl_u64!(i8); call_hasher_impl_u64!(i16); call_hasher_impl_u64!(i32); call_hasher_impl_u64!(i64); -call_hasher_impl_u64!(&u8); -call_hasher_impl_u64!(&u16); -call_hasher_impl_u64!(&u32); -call_hasher_impl_u64!(&u64); -call_hasher_impl_u64!(&i8); -call_hasher_impl_u64!(&i16); -call_hasher_impl_u64!(&i32); -call_hasher_impl_u64!(&i64); macro_rules! call_hasher_impl_fixed_length { ($typ:ty) => { + call_hasher_impl_fixed_length!(@internal $typ); + call_hasher_impl_fixed_length!(@internal &$typ); + call_hasher_impl_fixed_length!(@internal &&$typ); + call_hasher_impl_fixed_length!(@internal &&&$typ); + call_hasher_impl_fixed_length!(@internal &&&&$typ); + call_hasher_impl_fixed_length!(@internal &&&&&$typ); + }; + + (@internal $typ:ty) => { #[cfg(specialize)] impl CallHasher for $typ { #[inline] @@ -85,47 +99,69 @@ macro_rules! call_hasher_impl_fixed_length { } }; } - call_hasher_impl_fixed_length!(u128); call_hasher_impl_fixed_length!(i128); call_hasher_impl_fixed_length!(usize); call_hasher_impl_fixed_length!(isize); -call_hasher_impl_fixed_length!(&u128); -call_hasher_impl_fixed_length!(&i128); -call_hasher_impl_fixed_length!(&usize); -call_hasher_impl_fixed_length!(&isize); -#[cfg(specialize)] -impl CallHasher for [u8] { - #[inline] - fn get_hash(value: &H, random_state: &RandomState) -> u64 { - random_state.hash_as_str(value) - } -} +macro_rules! call_hasher_impl_str { + ($typ:ty) => { + call_hasher_impl_str!(@internal $typ); + call_hasher_impl_str!(@internal &$typ); + call_hasher_impl_str!(@internal &&$typ); + call_hasher_impl_str!(@internal &&&$typ); + call_hasher_impl_str!(@internal &&&&$typ); + call_hasher_impl_str!(@internal &&&&&$typ); + }; -#[cfg(specialize)] -impl CallHasher for Vec { - #[inline] - fn get_hash(value: &H, random_state: &RandomState) -> u64 { - random_state.hash_as_str(value) - } + (@internal $typ:ty) => { + #[cfg(specialize)] + impl CallHasher for $typ { + #[inline] + fn get_hash(value: &H, random_state: &RandomState) -> u64 { + random_state.hash_as_str(value) + } + } + }; } +call_hasher_impl_str!([u8]); +call_hasher_impl_str!(Box<[u8]>); +call_hasher_impl_str!(Vec); +call_hasher_impl_str!(Box>); +call_hasher_impl_str!(str); +call_hasher_impl_str!(Box); +call_hasher_impl_str!(String); +call_hasher_impl_str!(Box); +call_hasher_impl_str!(OsStr); +call_hasher_impl_str!(Box); +call_hasher_impl_str!(OsString); +call_hasher_impl_str!(Box); +call_hasher_impl_str!(Path); +call_hasher_impl_str!(Box); +call_hasher_impl_str!(PathBuf); +call_hasher_impl_str!(Box); -#[cfg(specialize)] -impl CallHasher for str { - #[inline] - fn get_hash(value: &H, random_state: &RandomState) -> u64 { - random_state.hash_as_str(value) - } -} +macro_rules! call_hasher_impl_fixed_str { + ($typ:ty) => { + call_hasher_impl_fixed_str!(@internal $typ); + call_hasher_impl_fixed_str!(@internal &$typ); + call_hasher_impl_fixed_str!(@internal &&$typ); + call_hasher_impl_fixed_str!(@internal &&&$typ); + call_hasher_impl_fixed_str!(@internal &&&&$typ); + call_hasher_impl_fixed_str!(@internal &&&&&$typ); + }; -#[cfg(all(specialize))] -impl CallHasher for String { - #[inline] - fn get_hash(value: &H, random_state: &RandomState) -> u64 { - random_state.hash_as_str(value) - } + (@internal $typ:ty) => { + #[cfg(specialize)] + impl CallHasher for $typ { + #[inline] + fn get_hash(value: &H, random_state: &RandomState) -> u64 { + random_state.hash_as_str(value) + } + } + }; } +call_hasher_impl_fixed_str!([u8; N]); #[cfg(test)] mod test { @@ -170,7 +206,7 @@ mod test { } #[test] - pub fn test_ref_independent() { + pub fn test_ref_independent_get_hash() { 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)); @@ -210,5 +246,95 @@ mod test { str::get_hash(&&"test", &build_hasher), <[u8]>::get_hash(&"test".to_string().into_bytes(), &build_hasher) ); + #[cfg(specialize)] + assert_eq!( + str::get_hash(&&"test", &build_hasher), + <[u8; 4]>::get_hash(b"test", &build_hasher) + ); + + let os_str = OsStr::new("test"); + let os_string = OsString::from("test"); + assert_eq!( + OsStr::get_hash(&&os_str, &build_hasher), + OsStr::get_hash(os_str, &build_hasher) + ); + assert_eq!( + OsStr::get_hash(&os_str, &build_hasher), + OsString::get_hash(&os_string, &build_hasher) + ); + assert_eq!( + OsStr::get_hash(&os_str, &build_hasher), + str::get_hash("test", &build_hasher) + ); + + let path = Path::new("test"); + let path_buf = PathBuf::from("test"); + assert_eq!( + Path::get_hash(&&path, &build_hasher), + Path::get_hash(path, &build_hasher) + ); + assert_eq!( + Path::get_hash(&path, &build_hasher), + PathBuf::get_hash(&path_buf, &build_hasher) + ); + assert_eq!( + Path::get_hash(&path, &build_hasher), + OsStr::get_hash(os_str, &build_hasher) + ); + } + + #[test] + pub fn test_ref_independent_hash_one() { + let build_hasher = RandomState::with_seeds(1, 2, 3, 4); + assert_eq!(build_hasher.hash_one(&&1u8), build_hasher.hash_one(&1)); + assert_eq!(build_hasher.hash_one(&&2u16), build_hasher.hash_one(&2)); + assert_eq!(build_hasher.hash_one(&&3u32), build_hasher.hash_one(&3)); + assert_eq!(build_hasher.hash_one(&&4u64), build_hasher.hash_one(&4)); + assert_eq!(build_hasher.hash_one(&&5u128), build_hasher.hash_one(&5i128)); + assert_eq!(build_hasher.hash_one(&&1i8), build_hasher.hash_one(&1)); + assert_eq!(build_hasher.hash_one(&&2i16), build_hasher.hash_one(&2)); + assert_eq!(build_hasher.hash_one(&&3i32), build_hasher.hash_one(&3)); + assert_eq!(build_hasher.hash_one(&&4i64), build_hasher.hash_one(&4)); + assert_eq!(build_hasher.hash_one(&&5isize), build_hasher.hash_one(&5usize)); + assert_eq!(build_hasher.hash_one(&"test"), build_hasher.hash_one("test")); + assert_eq!( + build_hasher.hash_one(&"test"), + build_hasher.hash_one(&"test".to_string()) + ); + assert_eq!(build_hasher.hash_one(&"test"), build_hasher.hash_one("test".as_bytes())); + + let build_hasher = RandomState::with_seeds(10, 20, 30, 40); + assert_eq!(build_hasher.hash_one(&&1u8), build_hasher.hash_one(&1)); + assert_eq!(build_hasher.hash_one(&&2u16), build_hasher.hash_one(&2)); + assert_eq!(build_hasher.hash_one(&&3u32), build_hasher.hash_one(&3)); + assert_eq!(build_hasher.hash_one(&&4u64), build_hasher.hash_one(&4)); + assert_eq!(build_hasher.hash_one(&&5u128), build_hasher.hash_one(&5i128)); + assert_eq!(build_hasher.hash_one(&&1i8), build_hasher.hash_one(&1)); + assert_eq!(build_hasher.hash_one(&&2i16), build_hasher.hash_one(&2)); + assert_eq!(build_hasher.hash_one(&&3i32), build_hasher.hash_one(&3)); + assert_eq!(build_hasher.hash_one(&&4i64), build_hasher.hash_one(&4)); + assert_eq!(build_hasher.hash_one(&&5isize), build_hasher.hash_one(&5usize)); + assert_eq!(build_hasher.hash_one(&&"test"), build_hasher.hash_one("test")); + assert_eq!( + build_hasher.hash_one(&&"test"), + build_hasher.hash_one(&"test".to_string()) + ); + assert_eq!( + build_hasher.hash_one(&&"test"), + build_hasher.hash_one(&"test".to_string().into_bytes()) + ); + assert_eq!(build_hasher.hash_one("test"), build_hasher.hash_one(b"test")); + + let os_str = OsStr::new("test"); + let os_string = OsString::from("test"); + assert_eq!(build_hasher.hash_one(&&os_str), build_hasher.hash_one(os_str)); + assert_eq!(build_hasher.hash_one(&os_str), build_hasher.hash_one(&os_string)); + assert_eq!(build_hasher.hash_one(os_str), build_hasher.hash_one("test")); + + let path = Path::new("test"); + let path_buf = PathBuf::from("test"); + assert_eq!(build_hasher.hash_one(&&path), build_hasher.hash_one(path)); + assert_eq!(build_hasher.hash_one(&path), build_hasher.hash_one(&path_buf)); + assert_eq!(build_hasher.hash_one(path), build_hasher.hash_one(os_str)); } }