1#[cfg(test)]
2#[path = "unordered_hash_map_test.rs"]
3mod test;
4
5#[cfg(not(feature = "std"))]
6use alloc::vec;
7use core::borrow::Borrow;
8use core::hash::{BuildHasher, Hash};
9use core::ops::Index;
10#[cfg(feature = "std")]
11use std::collections::HashMap;
12#[cfg(feature = "std")]
13pub use std::collections::hash_map::Entry;
14#[cfg(feature = "std")]
15use std::collections::hash_map::OccupiedEntry;
16#[cfg(feature = "std")]
17use std::collections::hash_map::RandomState;
18#[cfg(feature = "std")]
19use std::vec;
20
21#[cfg(not(feature = "std"))]
22use hashbrown::HashMap;
23#[cfg(not(feature = "std"))]
24pub use hashbrown::hash_map::Entry;
25use itertools::Itertools;
26
27#[cfg(feature = "std")]
33#[derive(Clone, Debug)]
34pub struct UnorderedHashMap<Key, Value, BH = RandomState>(HashMap<Key, Value, BH>);
35#[cfg(not(feature = "std"))]
36#[derive(Clone, Debug)]
37pub struct UnorderedHashMap<Key, Value, BH = hashbrown::hash_map::DefaultHashBuilder>(
38 HashMap<Key, Value, BH>,
39);
40
41impl<Key, Value, BH> UnorderedHashMap<Key, Value, BH> {
42 fn with_hasher(hash_builder: BH) -> Self {
43 Self(HashMap::<Key, Value, BH>::with_hasher(hash_builder))
44 }
45}
46
47impl<Key, Value, BH> PartialEq for UnorderedHashMap<Key, Value, BH>
48where
49 Key: Eq + Hash,
50 Value: PartialEq,
51 BH: BuildHasher,
52{
53 fn eq(&self, other: &Self) -> bool {
54 self.0 == other.0
55 }
56}
57
58impl<Key, Value, BH> Eq for UnorderedHashMap<Key, Value, BH>
59where
60 Key: Eq + Hash,
61 Value: Eq,
62 BH: BuildHasher,
63{
64}
65
66impl<Key, Value, BH> UnorderedHashMap<Key, Value, BH> {
67 pub fn len(&self) -> usize {
69 self.0.len()
70 }
71
72 pub fn is_empty(&self) -> bool {
74 self.0.is_empty()
75 }
76}
77
78impl<Key: Eq + Hash, Value, BH: BuildHasher> UnorderedHashMap<Key, Value, BH> {
79 pub fn get<Q>(&self, key: &Q) -> Option<&Value>
84 where
85 Key: Borrow<Q>,
86 Q: Hash + Eq + ?Sized,
87 {
88 self.0.get(key)
89 }
90
91 pub fn get_mut<Q>(&mut self, key: &Q) -> Option<&mut Value>
96 where
97 Key: Borrow<Q>,
98 Q: Hash + Eq + ?Sized,
99 {
100 self.0.get_mut(key)
101 }
102
103 pub fn insert(&mut self, key: Key, value: Value) -> Option<Value> {
111 self.0.insert(key, value)
112 }
113
114 pub fn remove<Q>(&mut self, key: &Q) -> Option<Value>
120 where
121 Key: Borrow<Q>,
122 Q: Hash + Eq + ?Sized,
123 {
124 self.0.remove(key)
125 }
126
127 #[cfg(feature = "std")]
128 pub fn entry(&mut self, key: Key) -> Entry<'_, Key, Value> {
130 self.0.entry(key)
131 }
132
133 #[cfg(not(feature = "std"))]
134 pub fn entry(&mut self, key: Key) -> Entry<'_, Key, Value, BH> {
136 self.0.entry(key)
137 }
138
139 pub fn contains_key<Q>(&self, key: &Q) -> bool
141 where
142 Q: ?Sized,
143 Key: Borrow<Q>,
144 Q: Hash + Eq,
145 {
146 self.0.contains_key(key)
147 }
148
149 pub fn map<TargetValue>(
151 &self,
152 mapper: impl Fn(&Value) -> TargetValue,
153 ) -> UnorderedHashMap<Key, TargetValue, BH>
154 where
155 Key: Clone,
156 BH: Clone,
157 {
158 self.0.iter().fold(
159 UnorderedHashMap::<_, _, _>::with_hasher(self.0.hasher().clone()),
160 |mut acc, (key, value)| {
161 match acc.entry(key.clone()) {
162 Entry::Occupied(_) => {
163 unreachable!("The original map should not contain duplicate keys.");
164 }
165 Entry::Vacant(vacant) => {
166 vacant.insert(mapper(value));
167 }
168 };
169 acc
170 },
171 )
172 }
173
174 pub fn aggregate_by<TargetKey: Eq + Hash, TargetValue>(
182 &self,
183 mapping_function: impl Fn(&Key) -> TargetKey,
184 reduce_function: impl Fn(&TargetValue, &Value) -> TargetValue,
185 default_value: &TargetValue,
186 ) -> UnorderedHashMap<TargetKey, TargetValue, BH>
187 where
188 BH: Clone,
189 {
190 self.0.iter().fold(
191 UnorderedHashMap::<_, _, _>::with_hasher(self.0.hasher().clone()),
192 |mut acc, (key, value)| {
193 let target_key = mapping_function(key);
194 match acc.entry(target_key) {
195 Entry::Occupied(occupied) => {
196 let old_target_value = occupied.into_mut();
197 let new_target_value = reduce_function(old_target_value, value);
198 *old_target_value = new_target_value;
199 }
200 Entry::Vacant(vacant) => {
201 let new_value = reduce_function(default_value, value);
202 vacant.insert(new_value);
203 }
204 };
205 acc
206 },
207 )
208 }
209
210 pub fn iter_sorted(&self) -> impl Iterator<Item = (&Key, &Value)>
218 where
219 Key: Ord,
220 {
221 self.0.iter().sorted_by_key(|(key, _)| *key)
222 }
223
224 pub fn into_iter_sorted(self) -> impl Iterator<Item = (Key, Value)>
226 where
227 Key: Ord + Clone,
228 {
229 self.0.into_iter().sorted_by_key(|(key, _)| (*key).clone())
230 }
231
232 pub fn iter_sorted_by_key<TargetKey, F>(&self, f: F) -> vec::IntoIter<(&Key, &Value)>
240 where
241 TargetKey: Ord,
242 F: FnMut(&(&Key, &Value)) -> TargetKey,
243 {
244 self.0.iter().sorted_by_key(f)
245 }
246
247 pub fn into_iter_sorted_by_key<TargetKey, F>(self, f: F) -> vec::IntoIter<(Key, Value)>
249 where
250 TargetKey: Ord,
251 F: FnMut(&(Key, Value)) -> TargetKey,
252 {
253 self.0.into_iter().sorted_by_key(f)
254 }
255
256 pub fn filter<P>(self, mut p: P) -> Self
259 where
260 BH: Default,
261 P: FnMut(&Key, &Value) -> bool,
262 {
263 Self(self.0.into_iter().filter(|(key, value)| p(key, value)).collect())
264 }
265
266 pub fn filter_cloned<P>(&self, mut p: P) -> Self
269 where
270 BH: Default,
271 P: FnMut(&Key, &Value) -> bool,
272 Key: Clone,
273 Value: Clone,
274 {
275 Self(
276 self.0
277 .iter()
278 .filter_map(
279 |(key, value)| {
280 if p(key, value) { Some((key.clone(), value.clone())) } else { None }
281 },
282 )
283 .collect(),
284 )
285 }
286
287 #[cfg(feature = "std")]
288 pub fn merge<HandleDuplicate>(&mut self, other: &Self, handle_duplicate: HandleDuplicate)
291 where
292 BH: Clone,
293 HandleDuplicate: Fn(OccupiedEntry<'_, Key, Value>, &Value),
294 Key: Clone,
295 Value: Clone,
296 {
297 for (key, value) in &other.0 {
298 match self.0.entry(key.clone()) {
299 Entry::Occupied(e) => {
300 handle_duplicate(e, value);
301 }
302 Entry::Vacant(e) => {
303 e.insert(value.clone());
304 }
305 }
306 }
307 }
308}
309
310impl<Key, Q: ?Sized, Value, BH: BuildHasher> Index<&Q> for UnorderedHashMap<Key, Value, BH>
311where
312 Key: Eq + Hash + Borrow<Q>,
313 Q: Eq + Hash,
314{
315 type Output = Value;
316
317 fn index(&self, key: &Q) -> &Self::Output {
318 self.0.index(key)
319 }
320}
321
322impl<Key, Value, BH: Default> Default for UnorderedHashMap<Key, Value, BH> {
323 #[cfg(feature = "std")]
324 fn default() -> Self {
325 Self(Default::default())
326 }
327 #[cfg(not(feature = "std"))]
328 fn default() -> Self {
329 Self(HashMap::with_hasher(Default::default()))
330 }
331}
332
333impl<Key: Hash + Eq, Value, BH: BuildHasher + Default> FromIterator<(Key, Value)>
334 for UnorderedHashMap<Key, Value, BH>
335{
336 fn from_iter<T: IntoIterator<Item = (Key, Value)>>(iter: T) -> Self {
337 Self(iter.into_iter().collect())
338 }
339}
340
341impl<Key: Hash + Eq, Value, const N: usize, BH: BuildHasher + Default> From<[(Key, Value); N]>
342 for UnorderedHashMap<Key, Value, BH>
343{
344 fn from(items: [(Key, Value); N]) -> Self {
345 Self(HashMap::from_iter(items))
346 }
347}