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