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