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}