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// Default hasher.
32cfg_if! {
33    if #[cfg(feature = "map-foldhash")] {
34        type DefaultHashBuilderInner = foldhash::fast::RandomState;
35    } else if #[cfg(feature = "map-fxhash")] {
36        type DefaultHashBuilderInner = FxBuildHasher;
37    } else if #[cfg(any(feature = "map-hashbrown", not(feature = "std")))] {
38        type DefaultHashBuilderInner = hashbrown::DefaultHashBuilder;
39    } else {
40        type DefaultHashBuilderInner = std::collections::hash_map::RandomState;
41    }
42}
43
44/// The default [`BuildHasher`] used by [`HashMap`](super::HashMap) and [`HashSet`](super::HashSet).
45///
46/// See [the module documentation](super) for more information on the default hasher.
47#[derive(Clone, Default)]
48#[allow(missing_copy_implementations, missing_debug_implementations)]
49pub struct DefaultHashBuilder {
50    inner: DefaultHashBuilderInner,
51}
52
53impl BuildHasher for DefaultHashBuilder {
54    type Hasher = DefaultHasher;
55
56    #[inline]
57    fn build_hasher(&self) -> Self::Hasher {
58        DefaultHasher { inner: self.inner.build_hasher() }
59    }
60
61    #[inline]
62    fn hash_one<T: Hash>(&self, x: T) -> u64
63    where
64        Self: Sized,
65        Self::Hasher: Hasher,
66    {
67        self.inner.hash_one(x)
68    }
69}
70
71/// The default [`Hasher`] used by [`HashMap`](super::HashMap) and [`HashSet`](super::HashSet).
72///
73/// See [the module documentation](super) for more information on the default hasher.
74#[derive(Clone)]
75#[allow(missing_debug_implementations)]
76pub struct DefaultHasher {
77    inner: <DefaultHashBuilderInner as BuildHasher>::Hasher,
78}
79
80macro_rules! forward_writes {
81    ($( $write:ident ( $ty:ty ) , )*) => {$(
82        #[inline(always)]
83        fn $write(&mut self, arg: $ty) {
84            self.inner.$write(arg);
85        }
86    )*}
87}
88
89impl Hasher for DefaultHasher {
90    forward_writes! {
91        write(&[u8]),
92        write_u8(u8),
93        write_u16(u16),
94        write_u32(u32),
95        write_u64(u64),
96        write_u128(u128),
97        write_usize(usize),
98        write_i8(i8),
99        write_i16(i16),
100        write_i32(i32),
101        write_i64(i64),
102        write_i128(i128),
103        write_isize(isize),
104    }
105
106    // feature(hasher_prefixfree_extras)
107    #[cfg(feature = "nightly")]
108    forward_writes! {
109        write_length_prefix(usize),
110        write_str(&str),
111    }
112
113    #[inline(always)]
114    fn finish(&self) -> u64 {
115        self.inner.finish()
116    }
117}