Skip to main content

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