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