alloy_primitives/map/
mod.rs

1//! Re-exports of map types and utilities.
2//!
3//! This module exports the following types:
4//! - [`HashMap`] and [`HashSet`] from the standard library or `hashbrown` crate. The
5//!   "map-hashbrown" feature can be used to force the use of `hashbrown`, and is required in
6//!   `no_std` environments.
7//! - [`IndexMap`] and [`IndexSet`] from the `indexmap` crate, if the "map-indexmap" feature is
8//!   enabled.
9//! - The previously-listed hash map types prefixed with `Fb`. These are type aliases with
10//!   [`FixedBytes<N>`][fb] as the key, and [`FbBuildHasher`] as the hasher builder. This hasher is
11//!   optimized for hashing fixed-size byte arrays, and wraps around the default hasher builder. It
12//!   performs best when the hasher is `fxhash`, which is enabled by default with the "map-fxhash"
13//!   feature.
14//! - The previously-listed hash map types prefixed with [`Selector`], [`Address`], and [`B256`].
15//!   These use [`FbBuildHasher`] with the respective fixed-size byte array as the key. See the
16//!   previous point for more information.
17//!
18//! Unless specified otherwise, the default hasher builder used by these types is
19//! [`DefaultHashBuilder`]. This hasher prioritizes speed over security. Users who require HashDoS
20//! resistance should enable the "rand" feature so that the hasher is initialized using a random
21//! seed.
22//!
23//! Note that using the types provided in this module may require using different APIs than the
24//! standard library as they might not be generic over the hasher state, such as using
25//! `HashMap::default()` instead of `HashMap::new()`.
26//!
27//! [fb]: crate::FixedBytes
28//! [`Selector`]: crate::Selector
29//! [`Address`]: crate::Address
30//! [`B256`]: crate::B256
31
32use cfg_if::cfg_if;
33
34mod hasher;
35pub use hasher::*;
36
37mod fixed;
38pub use fixed::*;
39
40// The `HashMap` implementation.
41// Use `hashbrown` if requested with "map-hashbrown" or required by `no_std`.
42cfg_if! {
43    if #[cfg(any(feature = "map-hashbrown", not(feature = "std")))] {
44        use hashbrown as imp;
45
46        /// A view into a single entry in a map, which may either be vacant or occupied.
47        ///
48        /// See [`Entry`](imp::hash_map::Entry) for more information.
49        pub type Entry<'a, K, V, S = DefaultHashBuilder> = imp::hash_map::Entry<'a, K, V, S>;
50        /// A view into an occupied entry in a `HashMap`. It is part of the [`Entry`] enum.
51        ///
52        /// See [`OccupiedEntry`](imp::hash_map::OccupiedEntry) for more information.
53        pub type OccupiedEntry<'a, K, V, S = DefaultHashBuilder> = imp::hash_map::OccupiedEntry<'a, K, V, S>;
54        /// A view into a vacant entry in a `HashMap`. It is part of the [`Entry`] enum.
55        ///
56        /// See [`VacantEntry`](imp::hash_map::VacantEntry) for more information.
57        pub type VacantEntry<'a, K, V, S = DefaultHashBuilder> = imp::hash_map::VacantEntry<'a, K, V, S>;
58    } else {
59        use hashbrown as _;
60        use std::collections as imp;
61        #[doc(no_inline)]
62        pub use imp::hash_map::{Entry, OccupiedEntry, VacantEntry};
63    }
64}
65
66#[doc(no_inline)]
67pub use imp::{hash_map, hash_set};
68
69/// A [`HashMap`](imp::HashMap) using the [default hasher](DefaultHasher).
70///
71/// See [`HashMap`](imp::HashMap) for more information.
72pub type HashMap<K, V, S = DefaultHashBuilder> = imp::HashMap<K, V, S>;
73/// A [`HashSet`](imp::HashSet) using the [default hasher](DefaultHasher).
74///
75/// See [`HashSet`](imp::HashSet) for more information.
76pub type HashSet<V, S = DefaultHashBuilder> = imp::HashSet<V, S>;
77
78// `indexmap` re-exports.
79cfg_if! {
80    if #[cfg(feature = "map-indexmap")] {
81        #[doc(no_inline)]
82        pub use indexmap::{self, map::Entry as IndexEntry};
83
84        /// [`IndexMap`](indexmap::IndexMap) using the [default hasher](DefaultHasher).
85        ///
86        /// See [`IndexMap`](indexmap::IndexMap) for more information.
87        pub type IndexMap<K, V, S = DefaultHashBuilder> = indexmap::IndexMap<K, V, S>;
88        /// [`IndexSet`](indexmap::IndexSet) using the [default hasher](DefaultHasher).
89        ///
90        /// See [`IndexSet`](indexmap::IndexSet) for more information.
91        pub type IndexSet<V, S = DefaultHashBuilder> = indexmap::IndexSet<V, S>;
92    }
93}
94
95/// This module contains the rayon parallel iterator types for hash maps (HashMap<K, V>).
96///
97/// You will rarely need to interact with it directly unless you have need to name one
98/// of the iterator types.
99#[cfg(feature = "rayon")]
100pub mod rayon {
101    use super::*;
102
103    cfg_if! {
104        if #[cfg(any(feature = "map-hashbrown", not(feature = "std")))] {
105            pub use hashbrown::hash_map::rayon::{
106                IntoParIter as IntoIter,
107                ParDrain as Drain,
108                ParIter as Iter,
109                ParIterMut as IterMut,
110                ParKeys as Keys,
111                ParValues as Values,
112                ParValuesMut as ValuesMut
113            };
114            use ::rayon as _;
115        } else {
116            pub use ::rayon::collections::hash_map::*;
117        }
118    }
119}
120
121#[cfg(test)]
122mod tests {
123    use super::*;
124
125    #[test]
126    fn default_hasher_builder_traits() {
127        let hash_builder = <DefaultHashBuilder as Default>::default();
128        let _hash_builder2 = <DefaultHashBuilder as Clone>::clone(&hash_builder);
129        let mut hasher =
130            <DefaultHashBuilder as core::hash::BuildHasher>::build_hasher(&hash_builder);
131
132        <DefaultHasher as core::hash::Hasher>::write_u8(&mut hasher, 0);
133        let _hasher2 = <DefaultHasher as Clone>::clone(&hasher);
134    }
135
136    // Check that the `Entry` types are correct.
137    fn use_entry(e: Entry<'_, u32, u64>) -> u64 {
138        match e {
139            Entry::Occupied(o) => {
140                let o: OccupiedEntry<'_, u32, u64> = o;
141                *o.get()
142            }
143            Entry::Vacant(v) => {
144                let v: VacantEntry<'_, u32, u64> = v;
145                *v.insert(0)
146            }
147        }
148    }
149
150    #[test]
151    fn test_entry() {
152        let mut map = HashMap::<u32, u64>::default();
153        map.insert(1, 1);
154        assert_eq!(use_entry(map.entry(0)), 0);
155        assert_eq!(use_entry(map.entry(1)), 1);
156        assert_eq!(use_entry(map.entry(2)), 0);
157    }
158}