Skip to main content

frozen_collections_core/maps/
hash_map.rs

1use crate::hash_tables::HashTable;
2use crate::hashers::BridgeHasher;
3use crate::maps::decl_macros::{
4    common_primary_funcs, debug_trait_funcs, get_disjoint_mut_funcs, hash_primary_funcs, index_trait_funcs, into_iterator_trait_funcs,
5    into_iterator_trait_mut_ref_funcs, into_iterator_trait_ref_funcs, len_trait_funcs, map_extras_trait_funcs, map_iteration_trait_funcs,
6    map_query_trait_funcs, partial_eq_trait_funcs,
7};
8use crate::maps::{IntoIter, IntoKeys, IntoValues, Iter, IterMut, Keys, Values, ValuesMut};
9use crate::traits::{CollectionMagnitude, Hasher, Len, Map, MapExtras, MapIteration, MapQuery, SmallCollection};
10use crate::utils::DeduppedVec;
11use core::fmt::{Debug, Formatter, Result};
12use core::ops::Index;
13use equivalent::Equivalent;
14
15#[cfg(not(feature = "std"))]
16use {alloc::string::String, alloc::vec::Vec};
17
18#[cfg(feature = "serde")]
19use {
20    crate::maps::decl_macros::serialize_trait_funcs,
21    serde::ser::SerializeMap,
22    serde::{Serialize, Serializer},
23};
24
25/// A general-purpose map implemented using a hash table.
26///
27#[doc = include_str!("../doc_snippets/private_api_warning.md")]
28#[doc = include_str!("../doc_snippets/about.md")]
29#[doc = include_str!("../doc_snippets/hash_warning.md")]
30///
31#[derive(Clone)]
32pub struct HashMap<K, V, CM = SmallCollection, H = BridgeHasher> {
33    entries: HashTable<(K, V), CM>,
34    hasher: H,
35}
36
37impl<K, V, CM, H> HashMap<K, V, CM, H>
38where
39    CM: CollectionMagnitude,
40{
41    /// Creates a frozen map.
42    ///
43    /// # Errors
44    ///
45    /// Fails if the number of entries in the vector, after deduplication, exceeds the
46    /// magnitude of the collection as specified by the `CM` generic argument.
47    pub fn with_hasher(entries: Vec<(K, V)>, hasher: H) -> core::result::Result<Self, String>
48    where
49        K: Eq,
50        H: Hasher<K>,
51    {
52        let entries = DeduppedVec::using_hash(entries, |x| hasher.hash_one(&x.0), |x, y| x.0 == y.0);
53        Self::from_dedupped(entries, hasher)
54    }
55
56    /// Creates a frozen map.
57    ///
58    /// # Errors
59    ///
60    /// Fails if the number of entries in the vector, after deduplication, exceeds the
61    /// magnitude of the collection as specified by the `CM` generic argument.
62    pub(crate) fn from_dedupped(entries: DeduppedVec<(K, V)>, hasher: H) -> core::result::Result<Self, String>
63    where
64        H: Hasher<K>,
65    {
66        let c = &hasher;
67        let h = |entry: &(K, V)| c.hash_one(&entry.0);
68        Ok(Self {
69            entries: HashTable::<(K, V), CM>::new(entries, h)?,
70            hasher,
71        })
72    }
73
74    hash_primary_funcs!();
75    common_primary_funcs!(non_const_len, entries entries);
76}
77
78impl<K, V, CM, H> Default for HashMap<K, V, CM, H>
79where
80    CM: CollectionMagnitude,
81    H: Default,
82{
83    fn default() -> Self {
84        Self {
85            entries: HashTable::default(),
86            hasher: H::default(),
87        }
88    }
89}
90
91impl<K, V, Q, CM, H> Map<K, V, Q> for HashMap<K, V, CM, H>
92where
93    CM: CollectionMagnitude,
94    Q: ?Sized + Equivalent<K>,
95    H: Hasher<Q>,
96{
97}
98
99impl<K, V, Q, CM, H> MapExtras<K, V, Q> for HashMap<K, V, CM, H>
100where
101    CM: CollectionMagnitude,
102    Q: ?Sized + Equivalent<K>,
103    H: Hasher<Q>,
104{
105    map_extras_trait_funcs!();
106}
107
108impl<K, V, Q, CM, H> MapQuery<Q, V> for HashMap<K, V, CM, H>
109where
110    CM: CollectionMagnitude,
111    Q: ?Sized + Equivalent<K>,
112    H: Hasher<Q>,
113{
114    map_query_trait_funcs!();
115}
116
117impl<K, V, CM, H> MapIteration<K, V> for HashMap<K, V, CM, H>
118where
119    CM: CollectionMagnitude,
120{
121    type Iterator<'a>
122        = Iter<'a, K, V>
123    where
124        K: 'a,
125        V: 'a,
126        CM: 'a,
127        H: 'a;
128
129    type KeyIterator<'a>
130        = Keys<'a, K, V>
131    where
132        K: 'a,
133        V: 'a,
134        CM: 'a,
135        H: 'a;
136
137    type ValueIterator<'a>
138        = Values<'a, K, V>
139    where
140        K: 'a,
141        V: 'a,
142        CM: 'a,
143        H: 'a;
144
145    type MutIterator<'a>
146        = IterMut<'a, K, V>
147    where
148        K: 'a,
149        V: 'a,
150        CM: 'a,
151        H: 'a;
152
153    type ValueMutIterator<'a>
154        = ValuesMut<'a, K, V>
155    where
156        K: 'a,
157        V: 'a,
158        CM: 'a,
159        H: 'a;
160
161    map_iteration_trait_funcs!();
162}
163
164impl<K, V, CM, H> Len for HashMap<K, V, CM, H>
165where
166    CM: CollectionMagnitude,
167{
168    len_trait_funcs!();
169}
170
171impl<Q, K, V, CM, H> Index<&Q> for HashMap<K, V, CM, H>
172where
173    Q: ?Sized + Equivalent<K>,
174    CM: CollectionMagnitude,
175    H: Hasher<Q>,
176{
177    index_trait_funcs!();
178}
179
180impl<K, V, CM, H> IntoIterator for HashMap<K, V, CM, H>
181where
182    CM: CollectionMagnitude,
183{
184    into_iterator_trait_funcs!();
185}
186
187impl<'a, K, V, CM, H> IntoIterator for &'a HashMap<K, V, CM, H>
188where
189    CM: CollectionMagnitude,
190{
191    into_iterator_trait_ref_funcs!();
192}
193
194impl<'a, K, V, CM, H> IntoIterator for &'a mut HashMap<K, V, CM, H>
195where
196    CM: CollectionMagnitude,
197{
198    into_iterator_trait_mut_ref_funcs!();
199}
200
201impl<K, V, MT, CM, H> PartialEq<MT> for HashMap<K, V, CM, H>
202where
203    K: PartialEq,
204    V: PartialEq,
205    MT: MapQuery<K, V>,
206    CM: CollectionMagnitude,
207    H: Hasher<K>,
208{
209    partial_eq_trait_funcs!();
210}
211
212impl<K, V, CM, H> Eq for HashMap<K, V, CM, H>
213where
214    K: Eq,
215    V: Eq,
216    CM: CollectionMagnitude,
217    H: Hasher<K>,
218{
219}
220
221impl<K, V, CM, H> Debug for HashMap<K, V, CM, H>
222where
223    K: Debug,
224    V: Debug,
225    CM: CollectionMagnitude,
226{
227    debug_trait_funcs!();
228}
229
230#[cfg(feature = "serde")]
231impl<K, V, CM, H> Serialize for HashMap<K, V, CM, H>
232where
233    K: Serialize,
234    V: Serialize,
235    CM: CollectionMagnitude,
236{
237    serialize_trait_funcs!();
238}
239
240#[cfg(test)]
241mod test {
242    use crate::hashers::BridgeHasher;
243    use crate::maps::HashMap;
244    use crate::traits::SmallCollection;
245
246    #[test]
247    fn fails_when_not_in_magnitude() {
248        let mut input: Vec<(i32, i32)> = Vec::new();
249        for i in 0..255 {
250            input.push((i, i));
251        }
252
253        let _ = HashMap::<_, _, SmallCollection, BridgeHasher>::with_hasher(input, BridgeHasher::default()).unwrap();
254
255        let mut input: Vec<(i32, i32)> = Vec::new();
256        for i in 0..256 {
257            input.push((i, i));
258        }
259
260        let _ = HashMap::<_, _, SmallCollection, BridgeHasher>::with_hasher(input, BridgeHasher::default()).unwrap_err();
261    }
262}