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}