iddqd/id_hash_map/imp.rs
1use super::{
2 Entry, IdHashItem, IntoIter, Iter, IterMut, OccupiedEntry, RefMut,
3 VacantEntry, tables::IdHashMapTables,
4};
5use crate::{
6 DefaultHashBuilder,
7 errors::DuplicateItem,
8 internal::{ValidateCompact, ValidationError},
9 support::{
10 alloc::{Allocator, Global, global_alloc},
11 borrow::DormantMutRef,
12 item_set::ItemSet,
13 map_hash::MapHash,
14 },
15};
16use alloc::collections::BTreeSet;
17use core::{
18 fmt,
19 hash::{BuildHasher, Hash},
20};
21use equivalent::Equivalent;
22use hashbrown::hash_table;
23
24/// A hash map where the key is part of the value.
25///
26/// The storage mechanism is a fast hash table of integer indexes to items, with
27/// these indexes stored in a hash table. This allows for efficient lookups by
28/// the key and prevents duplicates.
29///
30/// # Examples
31///
32/// ```
33/// # #[cfg(feature = "default-hasher")] {
34/// use iddqd::{IdHashItem, IdHashMap, id_upcast};
35///
36/// // Define a struct with a key.
37/// #[derive(Debug, PartialEq, Eq, Hash)]
38/// struct MyItem {
39/// id: String,
40/// value: u32,
41/// }
42///
43/// // Implement IdHashItem for the struct.
44/// impl IdHashItem for MyItem {
45/// // Keys can borrow from the item.
46/// type Key<'a> = &'a str;
47///
48/// fn key(&self) -> Self::Key<'_> {
49/// &self.id
50/// }
51///
52/// id_upcast!();
53/// }
54///
55/// // Create an IdHashMap and insert items.
56/// let mut map = IdHashMap::new();
57/// map.insert_unique(MyItem { id: "foo".to_string(), value: 42 }).unwrap();
58/// map.insert_unique(MyItem { id: "bar".to_string(), value: 20 }).unwrap();
59///
60/// // Look up items by their keys.
61/// assert_eq!(map.get("foo").unwrap().value, 42);
62/// assert_eq!(map.get("bar").unwrap().value, 20);
63/// assert!(map.get("baz").is_none());
64/// # }
65/// ```
66#[derive(Clone)]
67pub struct IdHashMap<T, S = DefaultHashBuilder, A: Allocator = Global> {
68 pub(super) items: ItemSet<T, A>,
69 tables: IdHashMapTables<S, A>,
70}
71
72impl<T: IdHashItem, S: Default, A: Allocator + Default> Default
73 for IdHashMap<T, S, A>
74{
75 fn default() -> Self {
76 Self {
77 items: ItemSet::with_capacity_in(0, A::default()),
78 tables: IdHashMapTables::default(),
79 }
80 }
81}
82
83#[cfg(feature = "default-hasher")]
84impl<T: IdHashItem> IdHashMap<T> {
85 /// Creates a new, empty `IdHashMap`.
86 ///
87 /// # Examples
88 ///
89 /// ```
90 /// # #[cfg(feature = "default-hasher")] {
91 /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
92 ///
93 /// #[derive(Debug, PartialEq, Eq, Hash)]
94 /// struct Item {
95 /// id: String,
96 /// value: u32,
97 /// }
98 ///
99 /// impl IdHashItem for Item {
100 /// type Key<'a> = &'a str;
101 /// fn key(&self) -> Self::Key<'_> {
102 /// &self.id
103 /// }
104 /// id_upcast!();
105 /// }
106 ///
107 /// let map: IdHashMap<Item> = IdHashMap::new();
108 /// assert!(map.is_empty());
109 /// assert_eq!(map.len(), 0);
110 /// # }
111 /// ```
112 #[inline]
113 pub fn new() -> Self {
114 Self { items: ItemSet::default(), tables: IdHashMapTables::default() }
115 }
116
117 /// Creates a new `IdHashMap` with the given capacity.
118 ///
119 /// # Examples
120 ///
121 /// ```
122 /// # #[cfg(feature = "default-hasher")] {
123 /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
124 ///
125 /// #[derive(Debug, PartialEq, Eq, Hash)]
126 /// struct Item {
127 /// id: String,
128 /// value: u32,
129 /// }
130 ///
131 /// impl IdHashItem for Item {
132 /// type Key<'a> = &'a str;
133 /// fn key(&self) -> Self::Key<'_> {
134 /// &self.id
135 /// }
136 /// id_upcast!();
137 /// }
138 ///
139 /// let map: IdHashMap<Item> = IdHashMap::with_capacity(10);
140 /// assert!(map.capacity() >= 10);
141 /// assert!(map.is_empty());
142 /// # }
143 /// ```
144 pub fn with_capacity(capacity: usize) -> Self {
145 Self {
146 items: ItemSet::with_capacity_in(capacity, global_alloc()),
147 tables: IdHashMapTables::with_capacity_and_hasher_in(
148 capacity,
149 DefaultHashBuilder::default(),
150 global_alloc(),
151 ),
152 }
153 }
154}
155
156impl<T: IdHashItem, S: Clone + BuildHasher> IdHashMap<T, S> {
157 /// Creates a new, empty `IdHashMap` with the given hasher.
158 ///
159 /// # Examples
160 ///
161 /// ```
162 /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
163 /// use std::collections::hash_map::RandomState;
164 ///
165 /// #[derive(Debug, PartialEq, Eq, Hash)]
166 /// struct Item {
167 /// id: String,
168 /// value: u32,
169 /// }
170 ///
171 /// impl IdHashItem for Item {
172 /// type Key<'a> = &'a str;
173 /// fn key(&self) -> Self::Key<'_> {
174 /// &self.id
175 /// }
176 /// id_upcast!();
177 /// }
178 ///
179 /// let hasher = RandomState::new();
180 /// let map: IdHashMap<Item, _> = IdHashMap::with_hasher(hasher);
181 /// assert!(map.is_empty());
182 /// ```
183 pub fn with_hasher(hasher: S) -> Self {
184 Self {
185 items: ItemSet::default(),
186 tables: IdHashMapTables::with_capacity_and_hasher_in(
187 0,
188 hasher,
189 global_alloc(),
190 ),
191 }
192 }
193
194 /// Creates a new `IdHashMap` with the given capacity and hasher.
195 ///
196 /// # Examples
197 ///
198 /// ```
199 /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
200 /// use std::collections::hash_map::RandomState;
201 ///
202 /// #[derive(Debug, PartialEq, Eq, Hash)]
203 /// struct Item {
204 /// id: String,
205 /// value: u32,
206 /// }
207 ///
208 /// impl IdHashItem for Item {
209 /// type Key<'a> = &'a str;
210 /// fn key(&self) -> Self::Key<'_> {
211 /// &self.id
212 /// }
213 /// id_upcast!();
214 /// }
215 ///
216 /// let hasher = RandomState::new();
217 /// let map: IdHashMap<Item, _> =
218 /// IdHashMap::with_capacity_and_hasher(10, hasher);
219 /// assert!(map.capacity() >= 10);
220 /// assert!(map.is_empty());
221 /// ```
222 pub fn with_capacity_and_hasher(capacity: usize, hasher: S) -> Self {
223 Self {
224 items: ItemSet::with_capacity_in(capacity, global_alloc()),
225 tables: IdHashMapTables::with_capacity_and_hasher_in(
226 capacity,
227 hasher,
228 global_alloc(),
229 ),
230 }
231 }
232}
233
234#[cfg(feature = "default-hasher")]
235impl<T: IdHashItem, A: Clone + Allocator> IdHashMap<T, DefaultHashBuilder, A> {
236 /// Creates a new empty `IdHashMap` using the given allocator.
237 ///
238 /// Requires the `allocator-api2` feature to be enabled.
239 ///
240 /// # Examples
241 ///
242 /// Using the [`bumpalo`](https://docs.rs/bumpalo) allocator:
243 ///
244 /// ```
245 /// # #[cfg(all(feature = "default-hasher", feature = "allocator-api2"))] {
246 /// use iddqd::{IdHashMap, IdHashItem, id_upcast};
247 /// # use iddqd_test_utils::bumpalo;
248 ///
249 /// #[derive(Debug, PartialEq, Eq, Hash)]
250 /// struct Item {
251 /// id: String,
252 /// value: u32,
253 /// }
254 ///
255 /// impl IdHashItem for Item {
256 /// type Key<'a> = &'a str;
257 /// fn key(&self) -> Self::Key<'_> { &self.id }
258 /// id_upcast!();
259 /// }
260 ///
261 /// // Define a new allocator.
262 /// let bump = bumpalo::Bump::new();
263 /// // Create a new IdHashMap using the allocator.
264 /// let map: IdHashMap<Item, _, &bumpalo::Bump> = IdHashMap::new_in(&bump);
265 /// assert!(map.is_empty());
266 /// # }
267 /// ```
268 pub fn new_in(alloc: A) -> Self {
269 Self {
270 items: ItemSet::with_capacity_in(0, alloc.clone()),
271 tables: IdHashMapTables::with_capacity_and_hasher_in(
272 0,
273 DefaultHashBuilder::default(),
274 alloc,
275 ),
276 }
277 }
278
279 /// Creates an empty `IdHashMap` with the specified capacity using the given
280 /// allocator.
281 ///
282 /// Requires the `allocator-api2` feature to be enabled.
283 ///
284 /// # Examples
285 ///
286 /// Using the [`bumpalo`](https://docs.rs/bumpalo) allocator:
287 ///
288 /// ```
289 /// # #[cfg(all(feature = "default-hasher", feature = "allocator-api2"))] {
290 /// use iddqd::{IdHashMap, IdHashItem, id_upcast};
291 /// # use iddqd_test_utils::bumpalo;
292 ///
293 /// #[derive(Debug, PartialEq, Eq, Hash)]
294 /// struct Item {
295 /// id: String,
296 /// value: u32,
297 /// }
298 ///
299 /// impl IdHashItem for Item {
300 /// type Key<'a> = &'a str;
301 /// fn key(&self) -> Self::Key<'_> { &self.id }
302 /// id_upcast!();
303 /// }
304 ///
305 /// // Define a new allocator.
306 /// let bump = bumpalo::Bump::new();
307 /// // Create a new IdHashMap with capacity using the allocator.
308 /// let map: IdHashMap<Item, _, &bumpalo::Bump> = IdHashMap::with_capacity_in(10, &bump);
309 /// assert!(map.capacity() >= 10);
310 /// assert!(map.is_empty());
311 /// # }
312 /// ```
313 pub fn with_capacity_in(capacity: usize, alloc: A) -> Self {
314 Self {
315 items: ItemSet::with_capacity_in(capacity, alloc.clone()),
316 tables: IdHashMapTables::with_capacity_and_hasher_in(
317 capacity,
318 DefaultHashBuilder::default(),
319 alloc,
320 ),
321 }
322 }
323}
324
325impl<T: IdHashItem, S: Clone + BuildHasher, A: Clone + Allocator>
326 IdHashMap<T, S, A>
327{
328 /// Creates a new, empty `IdHashMap` with the given hasher and allocator.
329 ///
330 /// Requires the `allocator-api2` feature to be enabled.
331 ///
332 /// # Examples
333 ///
334 /// Using the [`bumpalo`](https://docs.rs/bumpalo) allocator:
335 ///
336 /// ```
337 /// # #[cfg(feature = "allocator-api2")] {
338 /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
339 /// use std::collections::hash_map::RandomState;
340 /// # use iddqd_test_utils::bumpalo;
341 ///
342 /// #[derive(Debug, PartialEq, Eq, Hash)]
343 /// struct Item {
344 /// id: String,
345 /// value: u32,
346 /// }
347 ///
348 /// impl IdHashItem for Item {
349 /// type Key<'a> = &'a str;
350 /// fn key(&self) -> Self::Key<'_> {
351 /// &self.id
352 /// }
353 /// id_upcast!();
354 /// }
355 ///
356 /// // Define a new allocator.
357 /// let bump = bumpalo::Bump::new();
358 /// let hasher = RandomState::new();
359 /// // Create a new IdHashMap with hasher using the allocator.
360 /// let map: IdHashMap<Item, _, &bumpalo::Bump> =
361 /// IdHashMap::with_hasher_in(hasher, &bump);
362 /// assert!(map.is_empty());
363 /// # }
364 /// ```
365 pub fn with_hasher_in(hasher: S, alloc: A) -> Self {
366 Self {
367 items: ItemSet::with_capacity_in(0, alloc.clone()),
368 tables: IdHashMapTables::with_capacity_and_hasher_in(
369 0, hasher, alloc,
370 ),
371 }
372 }
373
374 /// Creates a new, empty `IdHashMap` with the given capacity, hasher, and
375 /// allocator.
376 ///
377 /// Requires the `allocator-api2` feature to be enabled.
378 ///
379 /// # Examples
380 ///
381 /// Using the [`bumpalo`](https://docs.rs/bumpalo) allocator:
382 ///
383 /// ```
384 /// # #[cfg(feature = "allocator-api2")] {
385 /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
386 /// use std::collections::hash_map::RandomState;
387 /// # use iddqd_test_utils::bumpalo;
388 ///
389 /// #[derive(Debug, PartialEq, Eq, Hash)]
390 /// struct Item {
391 /// id: String,
392 /// value: u32,
393 /// }
394 ///
395 /// impl IdHashItem for Item {
396 /// type Key<'a> = &'a str;
397 /// fn key(&self) -> Self::Key<'_> {
398 /// &self.id
399 /// }
400 /// id_upcast!();
401 /// }
402 ///
403 /// // Define a new allocator.
404 /// let bump = bumpalo::Bump::new();
405 /// let hasher = RandomState::new();
406 /// // Create a new IdHashMap with capacity and hasher using the allocator.
407 /// let map: IdHashMap<Item, _, &bumpalo::Bump> =
408 /// IdHashMap::with_capacity_and_hasher_in(10, hasher, &bump);
409 /// assert!(map.capacity() >= 10);
410 /// assert!(map.is_empty());
411 /// # }
412 /// ```
413 pub fn with_capacity_and_hasher_in(
414 capacity: usize,
415 hasher: S,
416 alloc: A,
417 ) -> Self {
418 Self {
419 items: ItemSet::with_capacity_in(capacity, alloc.clone()),
420 tables: IdHashMapTables::with_capacity_and_hasher_in(
421 capacity, hasher, alloc,
422 ),
423 }
424 }
425}
426
427impl<T: IdHashItem, S: Clone + BuildHasher, A: Allocator> IdHashMap<T, S, A> {
428 #[cfg(feature = "daft")]
429 pub(crate) fn hasher(&self) -> &S {
430 self.tables.hasher()
431 }
432
433 /// Returns the allocator.
434 ///
435 /// Requires the `allocator-api2` feature to be enabled.
436 ///
437 /// # Examples
438 ///
439 /// Using the [`bumpalo`](https://docs.rs/bumpalo) allocator:
440 ///
441 /// ```
442 /// # #[cfg(all(feature = "default-hasher", feature = "allocator-api2"))] {
443 /// use iddqd::{IdHashMap, IdHashItem, id_upcast};
444 /// # use iddqd_test_utils::bumpalo;
445 ///
446 /// #[derive(Debug, PartialEq, Eq, Hash)]
447 /// struct Item {
448 /// id: String,
449 /// value: u32,
450 /// }
451 ///
452 /// impl IdHashItem for Item {
453 /// type Key<'a> = &'a str;
454 /// fn key(&self) -> Self::Key<'_> { &self.id }
455 /// id_upcast!();
456 /// }
457 ///
458 /// // Define a new allocator.
459 /// let bump = bumpalo::Bump::new();
460 /// // Create a new IdHashMap using the allocator.
461 /// let map: IdHashMap<Item, _, &bumpalo::Bump> = IdHashMap::new_in(&bump);
462 /// let _allocator = map.allocator();
463 /// # }
464 /// ```
465 pub fn allocator(&self) -> &A {
466 self.items.allocator()
467 }
468
469 /// Returns the currently allocated capacity of the map.
470 ///
471 /// # Examples
472 ///
473 /// ```
474 /// # #[cfg(feature = "default-hasher")] {
475 /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
476 ///
477 /// #[derive(Debug, PartialEq, Eq, Hash)]
478 /// struct Item {
479 /// id: String,
480 /// value: u32,
481 /// }
482 ///
483 /// impl IdHashItem for Item {
484 /// type Key<'a> = &'a str;
485 /// fn key(&self) -> Self::Key<'_> {
486 /// &self.id
487 /// }
488 /// id_upcast!();
489 /// }
490 ///
491 /// let map: IdHashMap<Item> = IdHashMap::with_capacity(10);
492 /// assert!(map.capacity() >= 10);
493 /// # }
494 /// ```
495 pub fn capacity(&self) -> usize {
496 // items and tables.capacity might theoretically diverge: use
497 // items.capacity.
498 self.items.capacity()
499 }
500
501 /// Returns true if the map is empty.
502 ///
503 /// # Examples
504 ///
505 /// ```
506 /// # #[cfg(feature = "default-hasher")] {
507 /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
508 ///
509 /// #[derive(Debug, PartialEq, Eq, Hash)]
510 /// struct Item {
511 /// id: String,
512 /// value: u32,
513 /// }
514 ///
515 /// impl IdHashItem for Item {
516 /// type Key<'a> = &'a str;
517 /// fn key(&self) -> Self::Key<'_> {
518 /// &self.id
519 /// }
520 /// id_upcast!();
521 /// }
522 ///
523 /// let mut map = IdHashMap::new();
524 /// assert!(map.is_empty());
525 ///
526 /// map.insert_unique(Item { id: "foo".to_string(), value: 42 }).unwrap();
527 /// assert!(!map.is_empty());
528 /// # }
529 /// ```
530 #[inline]
531 pub fn is_empty(&self) -> bool {
532 self.items.is_empty()
533 }
534
535 /// Returns the number of items in the map.
536 ///
537 /// # Examples
538 ///
539 /// ```
540 /// # #[cfg(feature = "default-hasher")] {
541 /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
542 ///
543 /// #[derive(Debug, PartialEq, Eq, Hash)]
544 /// struct Item {
545 /// id: String,
546 /// value: u32,
547 /// }
548 ///
549 /// impl IdHashItem for Item {
550 /// type Key<'a> = &'a str;
551 /// fn key(&self) -> Self::Key<'_> {
552 /// &self.id
553 /// }
554 /// id_upcast!();
555 /// }
556 ///
557 /// let mut map = IdHashMap::new();
558 /// assert_eq!(map.len(), 0);
559 ///
560 /// map.insert_unique(Item { id: "foo".to_string(), value: 42 }).unwrap();
561 /// assert_eq!(map.len(), 1);
562 ///
563 /// map.insert_unique(Item { id: "bar".to_string(), value: 20 }).unwrap();
564 /// assert_eq!(map.len(), 2);
565 /// # }
566 /// ```
567 #[inline]
568 pub fn len(&self) -> usize {
569 self.items.len()
570 }
571
572 /// Iterates over the items in the map.
573 ///
574 /// Similar to [`HashMap`], the iteration order is arbitrary and not
575 /// guaranteed to be stable.
576 ///
577 /// # Examples
578 ///
579 /// ```
580 /// # #[cfg(feature = "default-hasher")] {
581 /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
582 ///
583 /// #[derive(Debug, PartialEq, Eq, Hash)]
584 /// struct Item {
585 /// id: String,
586 /// value: u32,
587 /// }
588 ///
589 /// impl IdHashItem for Item {
590 /// type Key<'a> = &'a str;
591 /// fn key(&self) -> Self::Key<'_> {
592 /// &self.id
593 /// }
594 /// id_upcast!();
595 /// }
596 ///
597 /// let mut map = IdHashMap::new();
598 /// map.insert_unique(Item { id: "foo".to_string(), value: 42 }).unwrap();
599 /// map.insert_unique(Item { id: "bar".to_string(), value: 20 }).unwrap();
600 ///
601 /// let mut values: Vec<u32> = map.iter().map(|item| item.value).collect();
602 /// values.sort();
603 /// assert_eq!(values, vec![20, 42]);
604 /// # }
605 /// ```
606 ///
607 /// [`HashMap`]: std::collections::HashMap
608 #[inline]
609 pub fn iter(&self) -> Iter<'_, T> {
610 Iter::new(&self.items)
611 }
612
613 /// Iterates over the items in the map, allowing for mutation.
614 ///
615 /// Similar to [`HashMap`], the iteration order is arbitrary and not
616 /// guaranteed to be stable.
617 ///
618 /// # Examples
619 ///
620 /// ```
621 /// # #[cfg(feature = "default-hasher")] {
622 /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
623 ///
624 /// #[derive(Debug, PartialEq, Eq, Hash)]
625 /// struct Item {
626 /// id: String,
627 /// value: u32,
628 /// }
629 ///
630 /// impl IdHashItem for Item {
631 /// type Key<'a> = &'a str;
632 /// fn key(&self) -> Self::Key<'_> {
633 /// &self.id
634 /// }
635 /// id_upcast!();
636 /// }
637 ///
638 /// let mut map = IdHashMap::new();
639 /// map.insert_unique(Item { id: "foo".to_string(), value: 42 }).unwrap();
640 /// map.insert_unique(Item { id: "bar".to_string(), value: 20 }).unwrap();
641 ///
642 /// for mut item in map.iter_mut() {
643 /// item.value *= 2;
644 /// }
645 ///
646 /// assert_eq!(map.get("foo").unwrap().value, 84);
647 /// assert_eq!(map.get("bar").unwrap().value, 40);
648 /// # }
649 /// ```
650 ///
651 /// [`HashMap`]: std::collections::HashMap
652 #[inline]
653 pub fn iter_mut(&mut self) -> IterMut<'_, T, S, A> {
654 IterMut::new(&self.tables, &mut self.items)
655 }
656
657 /// Checks general invariants of the map.
658 ///
659 /// The code below always upholds these invariants, but it's useful to have
660 /// an explicit check for tests.
661 #[doc(hidden)]
662 pub fn validate(
663 &self,
664 compactness: ValidateCompact,
665 ) -> Result<(), ValidationError>
666 where
667 T: fmt::Debug,
668 {
669 self.items.validate(compactness)?;
670 self.tables.validate(self.len(), compactness)?;
671
672 // Check that the indexes are all correct.
673 for (&ix, item) in self.items.iter() {
674 let key = item.key();
675 let Some(ix1) = self.find_index(&key) else {
676 return Err(ValidationError::general(format!(
677 "item at index {ix} has no key1 index"
678 )));
679 };
680
681 if ix1 != ix {
682 return Err(ValidationError::General(format!(
683 "item at index {ix} has mismatched indexes: ix1: {ix1}",
684 )));
685 }
686 }
687
688 Ok(())
689 }
690
691 /// Inserts a value into the map, removing and returning the conflicting
692 /// item, if any.
693 ///
694 /// # Examples
695 ///
696 /// ```
697 /// # #[cfg(feature = "default-hasher")] {
698 /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
699 ///
700 /// #[derive(Debug, PartialEq, Eq, Hash)]
701 /// struct Item {
702 /// id: String,
703 /// value: u32,
704 /// }
705 ///
706 /// impl IdHashItem for Item {
707 /// type Key<'a> = &'a str;
708 /// fn key(&self) -> Self::Key<'_> {
709 /// &self.id
710 /// }
711 /// id_upcast!();
712 /// }
713 ///
714 /// let mut map = IdHashMap::new();
715 ///
716 /// // First insertion returns None
717 /// let old = map.insert_overwrite(Item { id: "foo".to_string(), value: 42 });
718 /// assert!(old.is_none());
719 ///
720 /// // Second insertion with same key returns the old value
721 /// let old = map.insert_overwrite(Item { id: "foo".to_string(), value: 100 });
722 /// assert_eq!(old.unwrap().value, 42);
723 /// assert_eq!(map.get("foo").unwrap().value, 100);
724 /// # }
725 /// ```
726 #[doc(alias = "insert")]
727 pub fn insert_overwrite(&mut self, value: T) -> Option<T> {
728 // Trying to write this function for maximal efficiency can get very
729 // tricky, requiring delicate handling of indexes. We follow a very
730 // simple approach instead:
731 //
732 // 1. Remove items corresponding to the key that is already in the map.
733 // 2. Add the item to the map.
734
735 let duplicate = self.remove(&value.key());
736
737 if self.insert_unique(value).is_err() {
738 // We should never get here, because we just removed all the
739 // duplicates.
740 panic!("insert_unique failed after removing duplicates");
741 }
742
743 duplicate
744 }
745
746 /// Inserts a value into the set, returning an error if any duplicates were
747 /// added.
748 ///
749 /// # Examples
750 ///
751 /// ```
752 /// # #[cfg(feature = "default-hasher")] {
753 /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
754 ///
755 /// #[derive(Debug, PartialEq, Eq, Hash)]
756 /// struct Item {
757 /// id: String,
758 /// value: u32,
759 /// }
760 ///
761 /// impl IdHashItem for Item {
762 /// type Key<'a> = &'a str;
763 /// fn key(&self) -> Self::Key<'_> {
764 /// &self.id
765 /// }
766 /// id_upcast!();
767 /// }
768 ///
769 /// let mut map = IdHashMap::new();
770 ///
771 /// // First insertion succeeds
772 /// assert!(
773 /// map.insert_unique(Item { id: "foo".to_string(), value: 42 }).is_ok()
774 /// );
775 ///
776 /// // Second insertion with different key succeeds
777 /// assert!(
778 /// map.insert_unique(Item { id: "bar".to_string(), value: 20 }).is_ok()
779 /// );
780 ///
781 /// // Third insertion with duplicate key fails
782 /// assert!(
783 /// map.insert_unique(Item { id: "foo".to_string(), value: 100 }).is_err()
784 /// );
785 /// # }
786 /// ```
787 pub fn insert_unique(
788 &mut self,
789 value: T,
790 ) -> Result<(), DuplicateItem<T, &T>> {
791 let _ = self.insert_unique_impl(value)?;
792 Ok(())
793 }
794
795 /// Returns true if the map contains the given key.
796 ///
797 /// # Examples
798 ///
799 /// ```
800 /// # #[cfg(feature = "default-hasher")] {
801 /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
802 ///
803 /// #[derive(Debug, PartialEq, Eq, Hash)]
804 /// struct Item {
805 /// id: String,
806 /// value: u32,
807 /// }
808 ///
809 /// impl IdHashItem for Item {
810 /// type Key<'a> = &'a str;
811 /// fn key(&self) -> Self::Key<'_> {
812 /// &self.id
813 /// }
814 /// id_upcast!();
815 /// }
816 ///
817 /// let mut map = IdHashMap::new();
818 /// map.insert_unique(Item { id: "foo".to_string(), value: 42 }).unwrap();
819 ///
820 /// assert!(map.contains_key("foo"));
821 /// assert!(!map.contains_key("bar"));
822 /// # }
823 /// ```
824 pub fn contains_key<'a, Q>(&'a self, key1: &Q) -> bool
825 where
826 Q: ?Sized + Hash + Equivalent<T::Key<'a>>,
827 {
828 self.find_index(key1).is_some()
829 }
830
831 /// Gets a reference to the value associated with the given key.
832 ///
833 /// # Examples
834 ///
835 /// ```
836 /// # #[cfg(feature = "default-hasher")] {
837 /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
838 ///
839 /// #[derive(Debug, PartialEq, Eq, Hash)]
840 /// struct Item {
841 /// id: String,
842 /// value: u32,
843 /// }
844 ///
845 /// impl IdHashItem for Item {
846 /// type Key<'a> = &'a str;
847 /// fn key(&self) -> Self::Key<'_> {
848 /// &self.id
849 /// }
850 /// id_upcast!();
851 /// }
852 ///
853 /// let mut map = IdHashMap::new();
854 /// map.insert_unique(Item { id: "foo".to_string(), value: 42 }).unwrap();
855 ///
856 /// assert_eq!(map.get("foo").unwrap().value, 42);
857 /// assert!(map.get("bar").is_none());
858 /// # }
859 /// ```
860 pub fn get<'a, Q>(&'a self, key: &Q) -> Option<&'a T>
861 where
862 Q: ?Sized + Hash + Equivalent<T::Key<'a>>,
863 {
864 self.find_index(key).map(|ix| &self.items[ix])
865 }
866
867 /// Gets a mutable reference to the value associated with the given key.
868 ///
869 /// # Examples
870 ///
871 /// ```
872 /// # #[cfg(feature = "default-hasher")] {
873 /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
874 ///
875 /// #[derive(Debug, PartialEq, Eq, Hash)]
876 /// struct Item {
877 /// id: String,
878 /// value: u32,
879 /// }
880 ///
881 /// impl IdHashItem for Item {
882 /// type Key<'a> = &'a str;
883 /// fn key(&self) -> Self::Key<'_> {
884 /// &self.id
885 /// }
886 /// id_upcast!();
887 /// }
888 ///
889 /// let mut map = IdHashMap::new();
890 /// map.insert_unique(Item { id: "foo".to_string(), value: 42 }).unwrap();
891 ///
892 /// if let Some(mut item) = map.get_mut("foo") {
893 /// item.value = 100;
894 /// }
895 ///
896 /// assert_eq!(map.get("foo").unwrap().value, 100);
897 /// assert!(map.get_mut("bar").is_none());
898 /// # }
899 /// ```
900 pub fn get_mut<'a, Q>(&'a mut self, key: &Q) -> Option<RefMut<'a, T, S>>
901 where
902 Q: ?Sized + Hash + Equivalent<T::Key<'a>>,
903 {
904 let (dormant_map, index) = {
905 let (map, dormant_map) = DormantMutRef::new(self);
906 let index = map.find_index(key)?;
907 (dormant_map, index)
908 };
909
910 // SAFETY: `map` is not used after this point.
911 let awakened_map = unsafe { dormant_map.awaken() };
912 let item = &mut awakened_map.items[index];
913 let hashes = awakened_map.tables.make_hash(item);
914 Some(RefMut::new(hashes, item))
915 }
916
917 /// Removes an item from the map by its key.
918 ///
919 /// # Examples
920 ///
921 /// ```
922 /// # #[cfg(feature = "default-hasher")] {
923 /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
924 ///
925 /// #[derive(Debug, PartialEq, Eq, Hash)]
926 /// struct Item {
927 /// id: String,
928 /// value: u32,
929 /// }
930 ///
931 /// impl IdHashItem for Item {
932 /// type Key<'a> = &'a str;
933 /// fn key(&self) -> Self::Key<'_> {
934 /// &self.id
935 /// }
936 /// id_upcast!();
937 /// }
938 ///
939 /// let mut map = IdHashMap::new();
940 /// map.insert_unique(Item { id: "foo".to_string(), value: 42 }).unwrap();
941 ///
942 /// let removed = map.remove("foo");
943 /// assert_eq!(removed.unwrap().value, 42);
944 /// assert!(map.is_empty());
945 ///
946 /// // Removing non-existent key returns None
947 /// assert!(map.remove("bar").is_none());
948 /// # }
949 /// ```
950 pub fn remove<'a, Q>(&'a mut self, key: &Q) -> Option<T>
951 where
952 Q: ?Sized + Hash + Equivalent<T::Key<'a>>,
953 {
954 let (dormant_map, remove_index) = {
955 let (map, dormant_map) = DormantMutRef::new(self);
956 let remove_index = map.find_index(key)?;
957 (dormant_map, remove_index)
958 };
959
960 // SAFETY: `map` is not used after this point.
961 let awakened_map = unsafe { dormant_map.awaken() };
962
963 let value = awakened_map
964 .items
965 .remove(remove_index)
966 .expect("items missing key1 that was just retrieved");
967
968 // Remove the value from the tables.
969 let Ok(item1) =
970 awakened_map.tables.key_to_item.find_entry(&value.key(), |index| {
971 if index == remove_index {
972 value.key()
973 } else {
974 awakened_map.items[index].key()
975 }
976 })
977 else {
978 // The item was not found.
979 panic!("we just looked this item up");
980 };
981
982 item1.remove();
983
984 Some(value)
985 }
986
987 /// Retrieves an entry by its key.
988 ///
989 /// Due to borrow checker limitations, this always accepts an owned key
990 /// rather than a borrowed form of it.
991 ///
992 /// # Examples
993 ///
994 /// ```
995 /// # #[cfg(feature = "default-hasher")] {
996 /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
997 ///
998 /// #[derive(Debug, PartialEq, Eq, Hash)]
999 /// struct Item {
1000 /// id: String,
1001 /// value: u32,
1002 /// }
1003 ///
1004 /// impl IdHashItem for Item {
1005 /// type Key<'a> = &'a str;
1006 /// fn key(&self) -> Self::Key<'_> {
1007 /// &self.id
1008 /// }
1009 /// id_upcast!();
1010 /// }
1011 ///
1012 /// let mut map = IdHashMap::new();
1013 ///
1014 /// // Use entry API for conditional insertion
1015 /// map.entry("foo").or_insert(Item { id: "foo".to_string(), value: 42 });
1016 /// map.entry("bar").or_insert(Item { id: "bar".to_string(), value: 20 });
1017 ///
1018 /// assert_eq!(map.len(), 2);
1019 /// # }
1020 /// ```
1021 pub fn entry<'a>(&'a mut self, key: T::Key<'_>) -> Entry<'a, T, S, A> {
1022 // Why does this always take an owned key? Well, it would seem like we
1023 // should be able to pass in any Q that is equivalent. That results in
1024 // *this* code compiling fine, but callers have trouble using it because
1025 // the borrow checker believes the keys are borrowed for the full 'a
1026 // rather than a shorter lifetime.
1027 //
1028 // By accepting owned keys, we can use the upcast functions to convert
1029 // them to a shorter lifetime (so this function accepts T::Key<'_>
1030 // rather than T::Key<'a>).
1031 //
1032 // Really, the solution here is to allow GATs to require covariant
1033 // parameters. If that were allowed, the borrow checker should be able
1034 // to figure out that keys don't need to be borrowed for the full 'a,
1035 // just for some shorter lifetime.
1036 let (map, dormant_map) = DormantMutRef::new(self);
1037 let key = T::upcast_key(key);
1038 {
1039 // index is explicitly typed to show that it has a trivial Drop impl
1040 // that doesn't capture anything from map.
1041 let index: Option<usize> = map
1042 .tables
1043 .key_to_item
1044 .find_index(&key, |index| map.items[index].key());
1045 if let Some(index) = index {
1046 drop(key);
1047 return Entry::Occupied(
1048 // SAFETY: `map` is not used after this point.
1049 unsafe { OccupiedEntry::new(dormant_map, index) },
1050 );
1051 }
1052 }
1053 let hash = map.make_key_hash(&key);
1054 Entry::Vacant(
1055 // SAFETY: `map` is not used after this point.
1056 unsafe { VacantEntry::new(dormant_map, hash) },
1057 )
1058 }
1059
1060 fn find_index<'a, Q>(&'a self, k: &Q) -> Option<usize>
1061 where
1062 Q: Hash + Equivalent<T::Key<'a>> + ?Sized,
1063 {
1064 self.tables.key_to_item.find_index(k, |index| self.items[index].key())
1065 }
1066
1067 fn make_hash(&self, item: &T) -> MapHash<S> {
1068 self.tables.make_hash(item)
1069 }
1070
1071 fn make_key_hash(&self, key: &T::Key<'_>) -> MapHash<S> {
1072 self.tables.make_key_hash::<T>(key)
1073 }
1074
1075 pub(super) fn get_by_index(&self, index: usize) -> Option<&T> {
1076 self.items.get(index)
1077 }
1078
1079 pub(super) fn get_by_index_mut(
1080 &mut self,
1081 index: usize,
1082 ) -> Option<RefMut<'_, T, S>> {
1083 let hashes = self.make_hash(&self.items[index]);
1084 let item = &mut self.items[index];
1085 Some(RefMut::new(hashes, item))
1086 }
1087
1088 pub(super) fn insert_unique_impl(
1089 &mut self,
1090 value: T,
1091 ) -> Result<usize, DuplicateItem<T, &T>> {
1092 let mut duplicates = BTreeSet::new();
1093
1094 // Check for duplicates *before* inserting the new item, because we
1095 // don't want to partially insert the new item and then have to roll
1096 // back.
1097 let key = value.key();
1098
1099 let entry = match self
1100 .tables
1101 .key_to_item
1102 .entry(key, |index| self.items[index].key())
1103 {
1104 hash_table::Entry::Occupied(slot) => {
1105 duplicates.insert(*slot.get());
1106 None
1107 }
1108 hash_table::Entry::Vacant(slot) => Some(slot),
1109 };
1110
1111 if !duplicates.is_empty() {
1112 return Err(DuplicateItem::__internal_new(
1113 value,
1114 duplicates.iter().map(|ix| &self.items[*ix]).collect(),
1115 ));
1116 }
1117
1118 let next_index = self.items.insert_at_next_index(value);
1119 entry.unwrap().insert(next_index);
1120
1121 Ok(next_index)
1122 }
1123
1124 pub(super) fn remove_by_index(&mut self, remove_index: usize) -> Option<T> {
1125 let value = self.items.remove(remove_index)?;
1126
1127 // Remove the value from the tables.
1128 let Ok(item) =
1129 self.tables.key_to_item.find_entry(&value.key(), |index| {
1130 if index == remove_index {
1131 value.key()
1132 } else {
1133 self.items[index].key()
1134 }
1135 })
1136 else {
1137 // The item was not found.
1138 panic!("we just looked this item up");
1139 };
1140
1141 item.remove();
1142
1143 Some(value)
1144 }
1145
1146 pub(super) fn replace_at_index(&mut self, index: usize, value: T) -> T {
1147 // We check the key before removing it, to avoid leaving the map in an
1148 // inconsistent state.
1149 let old_key =
1150 self.get_by_index(index).expect("index is known to be valid").key();
1151 if T::upcast_key(old_key) != value.key() {
1152 panic!(
1153 "must insert a value with \
1154 the same key used to create the entry"
1155 );
1156 }
1157
1158 // Now that we know the key is the same, we can replace the value
1159 // directly without needing to tweak any tables.
1160 self.items.replace(index, value)
1161 }
1162}
1163
1164impl<'a, T, S: Clone + BuildHasher, A: Allocator> fmt::Debug
1165 for IdHashMap<T, S, A>
1166where
1167 T: IdHashItem + fmt::Debug,
1168 T::Key<'a>: fmt::Debug,
1169 T: 'a,
1170{
1171 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1172 let mut map = f.debug_map();
1173
1174 for item in self.iter() {
1175 let key = item.key();
1176
1177 // SAFETY:
1178 //
1179 // * Lifetime extension: for a type T and two lifetime params 'a and
1180 // 'b, T<'a> and T<'b> aren't guaranteed to have the same layout,
1181 // but (a) that is true today and (b) it would be shocking and
1182 // break half the Rust ecosystem if that were to change in the
1183 // future.
1184 // * We only use key within the scope of this block before immediately
1185 // dropping it. In particular, map.entry calls key.fmt() without
1186 // holding a reference to it.
1187 let key: T::Key<'a> =
1188 unsafe { core::mem::transmute::<T::Key<'_>, T::Key<'a>>(key) };
1189
1190 map.entry(&key, item);
1191 }
1192 map.finish()
1193 }
1194}
1195
1196impl<T: IdHashItem + PartialEq, S: Clone + BuildHasher, A: Allocator> PartialEq
1197 for IdHashMap<T, S, A>
1198{
1199 fn eq(&self, other: &Self) -> bool {
1200 // Implementing PartialEq for IdHashMap is tricky because IdHashMap is
1201 // not semantically like an IndexMap: two maps are equivalent even if
1202 // their items are in a different order. In other words, any permutation
1203 // of items is equivalent.
1204 //
1205 // We also can't sort the items because they're not necessarily Ord.
1206 //
1207 // So we write a custom equality check that checks that each key in one
1208 // map points to the same item as in the other map.
1209
1210 if self.items.len() != other.items.len() {
1211 return false;
1212 }
1213
1214 // Walk over all the items in the first map and check that they point to
1215 // the same item in the second map.
1216 for item in self.items.values() {
1217 let k1 = item.key();
1218
1219 // Check that the indexes are the same in the other map.
1220 let Some(other_ix) = other.find_index(&k1) else {
1221 return false;
1222 };
1223
1224 // Check that the other map's item is the same as this map's
1225 // item. (This is what we use the `PartialEq` bound on T for.)
1226 //
1227 // Because we've checked that other_ix is Some, we know that it is
1228 // valid and points to the expected item.
1229 let other_item = &other.items[other_ix];
1230 if item != other_item {
1231 return false;
1232 }
1233 }
1234
1235 true
1236 }
1237}
1238
1239// The Eq bound on T ensures that the TriHashMap forms an equivalence class.
1240impl<T: IdHashItem + Eq, S: Clone + BuildHasher, A: Allocator> Eq
1241 for IdHashMap<T, S, A>
1242{
1243}
1244
1245/// The `Extend` implementation overwrites duplicates. In the future, there will
1246/// also be an `extend_unique` method that will return an error.
1247///
1248/// # Examples
1249///
1250/// ```
1251/// # #[cfg(feature = "default-hasher")] {
1252/// use iddqd::{IdHashItem, IdHashMap, id_upcast};
1253///
1254/// #[derive(Debug, PartialEq, Eq, Hash)]
1255/// struct Item {
1256/// id: String,
1257/// value: u32,
1258/// }
1259///
1260/// impl IdHashItem for Item {
1261/// type Key<'a> = &'a str;
1262/// fn key(&self) -> Self::Key<'_> {
1263/// &self.id
1264/// }
1265/// id_upcast!();
1266/// }
1267///
1268/// let mut map = IdHashMap::new();
1269/// map.insert_unique(Item { id: "foo".to_string(), value: 42 }).unwrap();
1270///
1271/// let new_items = vec![
1272/// Item { id: "foo".to_string(), value: 100 }, // overwrites existing
1273/// Item { id: "bar".to_string(), value: 20 }, // new item
1274/// ];
1275///
1276/// map.extend(new_items);
1277/// assert_eq!(map.len(), 2);
1278/// assert_eq!(map.get("foo").unwrap().value, 100); // overwritten
1279/// assert_eq!(map.get("bar").unwrap().value, 20); // new
1280///
1281/// # }
1282/// ```
1283impl<T: IdHashItem, S: Clone + BuildHasher, A: Allocator> Extend<T>
1284 for IdHashMap<T, S, A>
1285{
1286 fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
1287 for item in iter {
1288 self.insert_overwrite(item);
1289 }
1290 }
1291}
1292
1293impl<'a, T: IdHashItem, S: Clone + BuildHasher, A: Allocator> IntoIterator
1294 for &'a IdHashMap<T, S, A>
1295{
1296 type Item = &'a T;
1297 type IntoIter = Iter<'a, T>;
1298
1299 /// Creates an iterator over references to the items in the map.
1300 ///
1301 /// # Examples
1302 ///
1303 /// ```
1304 /// # #[cfg(feature = "default-hasher")] {
1305 /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
1306 ///
1307 /// #[derive(Debug, PartialEq, Eq, Hash)]
1308 /// struct Item {
1309 /// id: String,
1310 /// value: u32,
1311 /// }
1312 ///
1313 /// impl IdHashItem for Item {
1314 /// type Key<'a> = &'a str;
1315 /// fn key(&self) -> Self::Key<'_> {
1316 /// &self.id
1317 /// }
1318 /// id_upcast!();
1319 /// }
1320 ///
1321 /// let mut map = IdHashMap::new();
1322 /// map.insert_unique(Item { id: "foo".to_string(), value: 42 }).unwrap();
1323 /// map.insert_unique(Item { id: "bar".to_string(), value: 20 }).unwrap();
1324 ///
1325 /// let mut values: Vec<u32> =
1326 /// (&map).into_iter().map(|item| item.value).collect();
1327 /// values.sort();
1328 /// assert_eq!(values, vec![20, 42]);
1329 /// # }
1330 /// ```
1331 #[inline]
1332 fn into_iter(self) -> Self::IntoIter {
1333 self.iter()
1334 }
1335}
1336
1337impl<'a, T: IdHashItem, S: Clone + BuildHasher, A: Allocator> IntoIterator
1338 for &'a mut IdHashMap<T, S, A>
1339{
1340 type Item = RefMut<'a, T, S>;
1341 type IntoIter = IterMut<'a, T, S, A>;
1342
1343 /// Creates an iterator over mutable references to the items in the map.
1344 ///
1345 /// # Examples
1346 ///
1347 /// ```
1348 /// # #[cfg(feature = "default-hasher")] {
1349 /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
1350 ///
1351 /// #[derive(Debug, PartialEq, Eq, Hash)]
1352 /// struct Item {
1353 /// id: String,
1354 /// value: u32,
1355 /// }
1356 ///
1357 /// impl IdHashItem for Item {
1358 /// type Key<'a> = &'a str;
1359 /// fn key(&self) -> Self::Key<'_> {
1360 /// &self.id
1361 /// }
1362 /// id_upcast!();
1363 /// }
1364 ///
1365 /// let mut map = IdHashMap::new();
1366 /// map.insert_unique(Item { id: "foo".to_string(), value: 42 }).unwrap();
1367 /// map.insert_unique(Item { id: "bar".to_string(), value: 20 }).unwrap();
1368 ///
1369 /// for mut item in &mut map {
1370 /// item.value *= 2;
1371 /// }
1372 ///
1373 /// assert_eq!(map.get("foo").unwrap().value, 84);
1374 /// assert_eq!(map.get("bar").unwrap().value, 40);
1375 /// # }
1376 /// ```
1377 #[inline]
1378 fn into_iter(self) -> Self::IntoIter {
1379 self.iter_mut()
1380 }
1381}
1382
1383impl<T: IdHashItem, S: Clone + BuildHasher, A: Allocator> IntoIterator
1384 for IdHashMap<T, S, A>
1385{
1386 type Item = T;
1387 type IntoIter = IntoIter<T, A>;
1388
1389 /// Consumes the map and creates an iterator over the owned items.
1390 ///
1391 /// # Examples
1392 ///
1393 /// ```
1394 /// # #[cfg(feature = "default-hasher")] {
1395 /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
1396 ///
1397 /// #[derive(Debug, PartialEq, Eq, Hash)]
1398 /// struct Item {
1399 /// id: String,
1400 /// value: u32,
1401 /// }
1402 ///
1403 /// impl IdHashItem for Item {
1404 /// type Key<'a> = &'a str;
1405 /// fn key(&self) -> Self::Key<'_> {
1406 /// &self.id
1407 /// }
1408 /// id_upcast!();
1409 /// }
1410 ///
1411 /// let mut map = IdHashMap::new();
1412 /// map.insert_unique(Item { id: "foo".to_string(), value: 42 }).unwrap();
1413 /// map.insert_unique(Item { id: "bar".to_string(), value: 20 }).unwrap();
1414 ///
1415 /// let mut values: Vec<u32> = map.into_iter().map(|item| item.value).collect();
1416 /// values.sort();
1417 /// assert_eq!(values, vec![20, 42]);
1418 /// # }
1419 /// ```
1420 #[inline]
1421 fn into_iter(self) -> Self::IntoIter {
1422 IntoIter::new(self.items)
1423 }
1424}
1425
1426/// The `FromIterator` implementation for `IdHashMap` overwrites duplicate
1427/// items.
1428///
1429/// # Examples
1430///
1431/// ```
1432/// # #[cfg(feature = "default-hasher")] {
1433/// use iddqd::{IdHashItem, IdHashMap, id_upcast};
1434///
1435/// #[derive(Debug, PartialEq, Eq, Hash)]
1436/// struct Item {
1437/// id: String,
1438/// value: u32,
1439/// }
1440///
1441/// impl IdHashItem for Item {
1442/// type Key<'a> = &'a str;
1443/// fn key(&self) -> Self::Key<'_> {
1444/// &self.id
1445/// }
1446/// id_upcast!();
1447/// }
1448///
1449/// let items = vec![
1450/// Item { id: "foo".to_string(), value: 42 },
1451/// Item { id: "bar".to_string(), value: 20 },
1452/// Item { id: "foo".to_string(), value: 100 }, // duplicate key, overwrites
1453/// ];
1454///
1455/// let map: IdHashMap<Item> = items.into_iter().collect();
1456/// assert_eq!(map.len(), 2);
1457/// assert_eq!(map.get("foo").unwrap().value, 100); // last value wins
1458/// assert_eq!(map.get("bar").unwrap().value, 20);
1459/// # }
1460/// ```
1461impl<T: IdHashItem, S: Default + Clone + BuildHasher, A: Allocator + Default>
1462 FromIterator<T> for IdHashMap<T, S, A>
1463{
1464 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
1465 let mut map = IdHashMap::default();
1466 for item in iter {
1467 map.insert_overwrite(item);
1468 }
1469 map
1470 }
1471}