summaryrefslogtreecommitdiffstats
path: root/third_party/rust/ahash/src/specialize.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/ahash/src/specialize.rs')
-rw-r--r--third_party/rust/ahash/src/specialize.rs162
1 files changed, 162 insertions, 0 deletions
diff --git a/third_party/rust/ahash/src/specialize.rs b/third_party/rust/ahash/src/specialize.rs
new file mode 100644
index 0000000000..2c0bc2d8af
--- /dev/null
+++ b/third_party/rust/ahash/src/specialize.rs
@@ -0,0 +1,162 @@
+#[cfg(feature = "specialize")]
+use crate::HasherExt;
+use core::hash::Hash;
+use core::hash::Hasher;
+
+/// 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. It does however consume the hasher in the process.
+/// #Example
+/// ```
+/// use std::hash::BuildHasher;
+/// use ahash::RandomState;
+/// use ahash::CallHasher;
+///
+/// let hash_builder = RandomState::new();
+/// //...
+/// let value = 17;
+/// let hash = value.get_hash(hash_builder.build_hasher());
+/// ```
+pub trait CallHasher: Hash {
+ fn get_hash<H: Hasher>(&self, hasher: H) -> u64;
+}
+
+#[cfg(not(feature = "specialize"))]
+impl<T> CallHasher for T
+where
+ T: Hash,
+{
+ #[inline]
+ fn get_hash<H: Hasher>(&self, mut hasher: H) -> u64 {
+ self.hash(&mut hasher);
+ hasher.finish()
+ }
+}
+
+#[cfg(feature = "specialize")]
+impl<T> CallHasher for T
+where
+ T: Hash,
+{
+ #[inline]
+ default fn get_hash<H: Hasher>(&self, mut hasher: H) -> u64 {
+ self.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>(&self, hasher: H) -> u64 {
+ hasher.hash_u64(*self 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>(&self, mut hasher: H) -> u64 {
+ hasher.write_u128(*self);
+ hasher.short_finish()
+ }
+}
+
+#[cfg(feature = "specialize")]
+impl CallHasher for i128 {
+ #[inline]
+ fn get_hash<H: Hasher>(&self, mut hasher: H) -> u64 {
+ hasher.write_u128(*self as u128);
+ hasher.short_finish()
+ }
+}
+
+#[cfg(feature = "specialize")]
+impl CallHasher for [u8] {
+ #[inline]
+ fn get_hash<H: Hasher>(&self, mut hasher: H) -> u64 {
+ hasher.write(self);
+ hasher.finish()
+ }
+}
+
+#[cfg(all(feature = "specialize", feature = "std"))]
+impl CallHasher for Vec<u8> {
+ #[inline]
+ fn get_hash<H: Hasher>(&self, mut hasher: H) -> u64 {
+ hasher.write(self);
+ hasher.finish()
+ }
+}
+
+#[cfg(feature = "specialize")]
+impl CallHasher for str {
+ #[inline]
+ fn get_hash<H: Hasher>(&self, mut hasher: H) -> u64 {
+ hasher.write(self.as_bytes());
+ hasher.finish()
+ }
+}
+
+#[cfg(all(feature = "specialize", feature = "std"))]
+impl CallHasher for String {
+ #[inline]
+ fn get_hash<H: Hasher>(&self, mut hasher: H) -> u64 {
+ hasher.write(self.as_bytes());
+ hasher.finish()
+ }
+}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+ use crate::*;
+
+ #[test]
+ #[cfg(feature = "specialize")]
+ pub fn test_specialized_invoked() {
+ let shortened = 0_u64.get_hash(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);
+ }
+
+ /// Tests that some non-trivial transformation takes place.
+ #[test]
+ pub fn test_input_processed() {
+ let hasher = || AHasher::new_with_keys(3, 2);
+ assert_ne!(0, 0_u64.get_hash(hasher()));
+ assert_ne!(1, 0_u64.get_hash(hasher()));
+ assert_ne!(2, 0_u64.get_hash(hasher()));
+ assert_ne!(3, 0_u64.get_hash(hasher()));
+ assert_ne!(4, 0_u64.get_hash(hasher()));
+ assert_ne!(5, 0_u64.get_hash(hasher()));
+
+ assert_ne!(0, 1_u64.get_hash(hasher()));
+ assert_ne!(1, 1_u64.get_hash(hasher()));
+ assert_ne!(2, 1_u64.get_hash(hasher()));
+ assert_ne!(3, 1_u64.get_hash(hasher()));
+ assert_ne!(4, 1_u64.get_hash(hasher()));
+ assert_ne!(5, 1_u64.get_hash(hasher()));
+
+ let xored = 0_u64.get_hash(hasher()) ^ 1_u64.get_hash(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);
+ }
+}