alloy_primitives/map/
hasher.rs

1use cfg_if::cfg_if;
2use core::hash::{BuildHasher, Hash, Hasher};
3
4// Faster hashers.
5cfg_if! {
6    if #[cfg(feature = "map-fxhash")] {
7        #[doc(no_inline)]
8        pub use rustc_hash::{self, FxHasher};
9
10        cfg_if! {
11            if #[cfg(all(feature = "std", feature = "rand"))] {
12                use rustc_hash::FxRandomState as FxBuildHasherInner;
13            } else {
14                use rustc_hash::FxBuildHasher as FxBuildHasherInner;
15            }
16        }
17
18        /// The [`FxHasher`] hasher builder.
19        ///
20        /// This is [`rustc_hash::FxBuildHasher`], unless both the "std" and "rand" features are
21        /// enabled, in which case it will be [`rustc_hash::FxRandomState`] for better security at
22        /// very little cost.
23        pub type FxBuildHasher = FxBuildHasherInner;
24    }
25}
26
27#[cfg(feature = "map-foldhash")]
28#[doc(no_inline)]
29pub use foldhash;
30
31#[cfg(feature = "map-rapidhash")]
32#[doc(no_inline)]
33pub use rapidhash;
34
35// Default hasher.
36cfg_if! {
37    if #[cfg(feature = "map-foldhash")] {
38        type DefaultHashBuilderInner = foldhash::fast::RandomState;
39    } else if #[cfg(feature = "map-rapidhash")] {
40        type DefaultHashBuilderInner = rapidhash::fast::RandomState;
41    } else if #[cfg(feature = "map-fxhash")] {
42        type DefaultHashBuilderInner = FxBuildHasher;
43    } else if #[cfg(any(feature = "map-hashbrown", not(feature = "std")))] {
44        type DefaultHashBuilderInner = hashbrown::DefaultHashBuilder;
45    } else {
46        type DefaultHashBuilderInner = std::collections::hash_map::RandomState;
47    }
48}
49
50/// The default [`BuildHasher`] used by [`HashMap`](super::HashMap) and [`HashSet`](super::HashSet).
51///
52/// See [the module documentation](super) for more information on the default hasher.
53#[derive(Clone, Default)]
54#[allow(missing_copy_implementations, missing_debug_implementations)]
55pub struct DefaultHashBuilder {
56    inner: DefaultHashBuilderInner,
57}
58
59impl BuildHasher for DefaultHashBuilder {
60    type Hasher = DefaultHasher;
61
62    #[inline]
63    fn build_hasher(&self) -> Self::Hasher {
64        DefaultHasher { inner: self.inner.build_hasher() }
65    }
66
67    #[inline]
68    fn hash_one<T: Hash>(&self, x: T) -> u64
69    where
70        Self: Sized,
71        Self::Hasher: Hasher,
72    {
73        self.inner.hash_one(x)
74    }
75}
76
77/// The default [`Hasher`] used by [`HashMap`](super::HashMap) and [`HashSet`](super::HashSet).
78///
79/// See [the module documentation](super) for more information on the default hasher.
80#[derive(Clone)]
81#[allow(missing_debug_implementations)]
82pub struct DefaultHasher {
83    inner: <DefaultHashBuilderInner as BuildHasher>::Hasher,
84}
85
86macro_rules! forward_writes {
87    ($( $write:ident ( $ty:ty ) , )*) => {$(
88        #[inline(always)]
89        fn $write(&mut self, arg: $ty) {
90            self.inner.$write(arg);
91        }
92    )*}
93}
94
95impl Hasher for DefaultHasher {
96    forward_writes! {
97        write(&[u8]),
98        write_u8(u8),
99        write_u16(u16),
100        write_u32(u32),
101        write_u64(u64),
102        write_u128(u128),
103        write_usize(usize),
104        write_i8(i8),
105        write_i16(i16),
106        write_i32(i32),
107        write_i64(i64),
108        write_i128(i128),
109        write_isize(isize),
110    }
111
112    // feature(hasher_prefixfree_extras)
113    #[cfg(feature = "nightly")]
114    forward_writes! {
115        write_length_prefix(usize),
116        write_str(&str),
117    }
118
119    #[inline(always)]
120    fn finish(&self) -> u64 {
121        self.inner.finish()
122    }
123}