Skip to main content

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        ItemIndex,
11        alloc::{Allocator, Global, global_alloc},
12        borrow::DormantMutRef,
13        item_set::ItemSet,
14        map_hash::MapHash,
15    },
16};
17use alloc::collections::BTreeSet;
18use core::{
19    fmt,
20    hash::{BuildHasher, Hash},
21};
22use equivalent::Equivalent;
23use hashbrown::hash_table;
24
25/// A hash map where the key is part of the value.
26///
27/// The storage mechanism is a fast hash table of integer indexes to items, with
28/// these indexes stored in a hash table. This allows for efficient lookups by
29/// the key and prevents duplicates.
30///
31/// # Examples
32///
33/// ```
34/// # #[cfg(feature = "default-hasher")] {
35/// use iddqd::{IdHashItem, IdHashMap, id_upcast};
36///
37/// // Define a struct with a key.
38/// #[derive(Debug, PartialEq, Eq, Hash)]
39/// struct MyItem {
40///     id: String,
41///     value: u32,
42/// }
43///
44/// // Implement IdHashItem for the struct.
45/// impl IdHashItem for MyItem {
46///     // Keys can borrow from the item.
47///     type Key<'a> = &'a str;
48///
49///     fn key(&self) -> Self::Key<'_> {
50///         &self.id
51///     }
52///
53///     id_upcast!();
54/// }
55///
56/// // Create an IdHashMap and insert items.
57/// let mut map = IdHashMap::new();
58/// map.insert_unique(MyItem { id: "foo".to_string(), value: 42 }).unwrap();
59/// map.insert_unique(MyItem { id: "bar".to_string(), value: 20 }).unwrap();
60///
61/// // Look up items by their keys.
62/// assert_eq!(map.get("foo").unwrap().value, 42);
63/// assert_eq!(map.get("bar").unwrap().value, 20);
64/// assert!(map.get("baz").is_none());
65/// # }
66/// ```
67#[derive(Clone)]
68pub struct IdHashMap<T, S = DefaultHashBuilder, A: Allocator = Global> {
69    pub(super) items: ItemSet<T, A>,
70    pub(super) tables: IdHashMapTables<S, A>,
71}
72
73impl<T: IdHashItem, S: Default, A: Allocator + Default> Default
74    for IdHashMap<T, S, A>
75{
76    fn default() -> Self {
77        Self {
78            items: ItemSet::with_capacity_in(0, A::default()),
79            tables: IdHashMapTables::default(),
80        }
81    }
82}
83
84#[cfg(feature = "default-hasher")]
85impl<T: IdHashItem> IdHashMap<T> {
86    /// Creates a new, empty `IdHashMap`.
87    ///
88    /// # Examples
89    ///
90    /// ```
91    /// # #[cfg(feature = "default-hasher")] {
92    /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
93    ///
94    /// #[derive(Debug, PartialEq, Eq, Hash)]
95    /// struct Item {
96    ///     id: String,
97    ///     value: u32,
98    /// }
99    ///
100    /// impl IdHashItem for Item {
101    ///     type Key<'a> = &'a str;
102    ///     fn key(&self) -> Self::Key<'_> {
103    ///         &self.id
104    ///     }
105    ///     id_upcast!();
106    /// }
107    ///
108    /// let map: IdHashMap<Item> = IdHashMap::new();
109    /// assert!(map.is_empty());
110    /// assert_eq!(map.len(), 0);
111    /// # }
112    /// ```
113    #[inline]
114    pub fn new() -> Self {
115        Self { items: ItemSet::new(), tables: IdHashMapTables::default() }
116    }
117
118    /// Creates a new `IdHashMap` with the given capacity.
119    ///
120    /// # Examples
121    ///
122    /// ```
123    /// # #[cfg(feature = "default-hasher")] {
124    /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
125    ///
126    /// #[derive(Debug, PartialEq, Eq, Hash)]
127    /// struct Item {
128    ///     id: String,
129    ///     value: u32,
130    /// }
131    ///
132    /// impl IdHashItem for Item {
133    ///     type Key<'a> = &'a str;
134    ///     fn key(&self) -> Self::Key<'_> {
135    ///         &self.id
136    ///     }
137    ///     id_upcast!();
138    /// }
139    ///
140    /// let map: IdHashMap<Item> = IdHashMap::with_capacity(10);
141    /// assert!(map.capacity() >= 10);
142    /// assert!(map.is_empty());
143    /// # }
144    /// ```
145    pub fn with_capacity(capacity: usize) -> Self {
146        Self {
147            items: ItemSet::with_capacity_in(capacity, global_alloc()),
148            tables: IdHashMapTables::with_capacity_and_hasher_in(
149                capacity,
150                DefaultHashBuilder::default(),
151                global_alloc(),
152            ),
153        }
154    }
155}
156
157impl<T: IdHashItem, S: BuildHasher> IdHashMap<T, S> {
158    /// Creates a new, empty `IdHashMap` with the given hasher.
159    ///
160    /// # Examples
161    ///
162    /// ```
163    /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
164    /// use std::collections::hash_map::RandomState;
165    ///
166    /// #[derive(Debug, PartialEq, Eq, Hash)]
167    /// struct Item {
168    ///     id: String,
169    ///     value: u32,
170    /// }
171    ///
172    /// impl IdHashItem for Item {
173    ///     type Key<'a> = &'a str;
174    ///     fn key(&self) -> Self::Key<'_> {
175    ///         &self.id
176    ///     }
177    ///     id_upcast!();
178    /// }
179    ///
180    /// let hasher = RandomState::new();
181    /// let map: IdHashMap<Item, _> = IdHashMap::with_hasher(hasher);
182    /// assert!(map.is_empty());
183    /// ```
184    pub const fn with_hasher(hasher: S) -> Self {
185        Self {
186            items: ItemSet::new(),
187            tables: IdHashMapTables::with_hasher_in(hasher, global_alloc()),
188        }
189    }
190
191    /// Creates a new `IdHashMap` with the given capacity and hasher.
192    ///
193    /// # Examples
194    ///
195    /// ```
196    /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
197    /// use std::collections::hash_map::RandomState;
198    ///
199    /// #[derive(Debug, PartialEq, Eq, Hash)]
200    /// struct Item {
201    ///     id: String,
202    ///     value: u32,
203    /// }
204    ///
205    /// impl IdHashItem for Item {
206    ///     type Key<'a> = &'a str;
207    ///     fn key(&self) -> Self::Key<'_> {
208    ///         &self.id
209    ///     }
210    ///     id_upcast!();
211    /// }
212    ///
213    /// let hasher = RandomState::new();
214    /// let map: IdHashMap<Item, _> =
215    ///     IdHashMap::with_capacity_and_hasher(10, hasher);
216    /// assert!(map.capacity() >= 10);
217    /// assert!(map.is_empty());
218    /// ```
219    pub fn with_capacity_and_hasher(capacity: usize, hasher: S) -> Self {
220        Self {
221            items: ItemSet::with_capacity_in(capacity, global_alloc()),
222            tables: IdHashMapTables::with_capacity_and_hasher_in(
223                capacity,
224                hasher,
225                global_alloc(),
226            ),
227        }
228    }
229}
230
231#[cfg(feature = "default-hasher")]
232impl<T: IdHashItem, A: Clone + Allocator> IdHashMap<T, DefaultHashBuilder, A> {
233    /// Creates a new empty `IdHashMap` using the given allocator.
234    ///
235    /// Requires the `allocator-api2` feature to be enabled.
236    ///
237    /// # Examples
238    ///
239    /// Using the [`bumpalo`](https://docs.rs/bumpalo) allocator:
240    ///
241    /// ```
242    /// # #[cfg(all(feature = "default-hasher", feature = "allocator-api2"))] {
243    /// use iddqd::{IdHashMap, IdHashItem, id_upcast};
244    /// # use iddqd_test_utils::bumpalo;
245    ///
246    /// #[derive(Debug, PartialEq, Eq, Hash)]
247    /// struct Item {
248    ///     id: String,
249    ///     value: u32,
250    /// }
251    ///
252    /// impl IdHashItem for Item {
253    ///     type Key<'a> = &'a str;
254    ///     fn key(&self) -> Self::Key<'_> { &self.id }
255    ///     id_upcast!();
256    /// }
257    ///
258    /// // Define a new allocator.
259    /// let bump = bumpalo::Bump::new();
260    /// // Create a new IdHashMap using the allocator.
261    /// let map: IdHashMap<Item, _, &bumpalo::Bump> = IdHashMap::new_in(&bump);
262    /// assert!(map.is_empty());
263    /// # }
264    /// ```
265    pub fn new_in(alloc: A) -> Self {
266        Self {
267            items: ItemSet::with_capacity_in(0, alloc.clone()),
268            tables: IdHashMapTables::with_capacity_and_hasher_in(
269                0,
270                DefaultHashBuilder::default(),
271                alloc,
272            ),
273        }
274    }
275
276    /// Creates an empty `IdHashMap` with the specified capacity using the given
277    /// allocator.
278    ///
279    /// Requires the `allocator-api2` feature to be enabled.
280    ///
281    /// # Examples
282    ///
283    /// Using the [`bumpalo`](https://docs.rs/bumpalo) allocator:
284    ///
285    /// ```
286    /// # #[cfg(all(feature = "default-hasher", feature = "allocator-api2"))] {
287    /// use iddqd::{IdHashMap, IdHashItem, id_upcast};
288    /// # use iddqd_test_utils::bumpalo;
289    ///
290    /// #[derive(Debug, PartialEq, Eq, Hash)]
291    /// struct Item {
292    ///     id: String,
293    ///     value: u32,
294    /// }
295    ///
296    /// impl IdHashItem for Item {
297    ///     type Key<'a> = &'a str;
298    ///     fn key(&self) -> Self::Key<'_> { &self.id }
299    ///     id_upcast!();
300    /// }
301    ///
302    /// // Define a new allocator.
303    /// let bump = bumpalo::Bump::new();
304    /// // Create a new IdHashMap with capacity using the allocator.
305    /// let map: IdHashMap<Item, _, &bumpalo::Bump> = IdHashMap::with_capacity_in(10, &bump);
306    /// assert!(map.capacity() >= 10);
307    /// assert!(map.is_empty());
308    /// # }
309    /// ```
310    pub fn with_capacity_in(capacity: usize, alloc: A) -> Self {
311        Self {
312            items: ItemSet::with_capacity_in(capacity, alloc.clone()),
313            tables: IdHashMapTables::with_capacity_and_hasher_in(
314                capacity,
315                DefaultHashBuilder::default(),
316                alloc,
317            ),
318        }
319    }
320}
321
322impl<T: IdHashItem, S: BuildHasher, A: Clone + Allocator> IdHashMap<T, S, A> {
323    /// Creates a new, empty `IdHashMap` with the given hasher and allocator.
324    ///
325    /// Requires the `allocator-api2` feature to be enabled.
326    ///
327    /// # Examples
328    ///
329    /// Using the [`bumpalo`](https://docs.rs/bumpalo) allocator:
330    ///
331    /// ```
332    /// # #[cfg(feature = "allocator-api2")] {
333    /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
334    /// use std::collections::hash_map::RandomState;
335    /// # use iddqd_test_utils::bumpalo;
336    ///
337    /// #[derive(Debug, PartialEq, Eq, Hash)]
338    /// struct Item {
339    ///     id: String,
340    ///     value: u32,
341    /// }
342    ///
343    /// impl IdHashItem for Item {
344    ///     type Key<'a> = &'a str;
345    ///     fn key(&self) -> Self::Key<'_> {
346    ///         &self.id
347    ///     }
348    ///     id_upcast!();
349    /// }
350    ///
351    /// // Define a new allocator.
352    /// let bump = bumpalo::Bump::new();
353    /// let hasher = RandomState::new();
354    /// // Create a new IdHashMap with hasher using the allocator.
355    /// let map: IdHashMap<Item, _, &bumpalo::Bump> =
356    ///     IdHashMap::with_hasher_in(hasher, &bump);
357    /// assert!(map.is_empty());
358    /// # }
359    /// ```
360    pub fn with_hasher_in(hasher: S, alloc: A) -> Self {
361        Self {
362            items: ItemSet::new_in(alloc.clone()),
363            tables: IdHashMapTables::with_hasher_in(hasher, alloc),
364        }
365    }
366
367    /// Creates a new, empty `IdHashMap` with the given capacity, hasher, and
368    /// allocator.
369    ///
370    /// Requires the `allocator-api2` feature to be enabled.
371    ///
372    /// # Examples
373    ///
374    /// Using the [`bumpalo`](https://docs.rs/bumpalo) allocator:
375    ///
376    /// ```
377    /// # #[cfg(feature = "allocator-api2")] {
378    /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
379    /// use std::collections::hash_map::RandomState;
380    /// # use iddqd_test_utils::bumpalo;
381    ///
382    /// #[derive(Debug, PartialEq, Eq, Hash)]
383    /// struct Item {
384    ///     id: String,
385    ///     value: u32,
386    /// }
387    ///
388    /// impl IdHashItem for Item {
389    ///     type Key<'a> = &'a str;
390    ///     fn key(&self) -> Self::Key<'_> {
391    ///         &self.id
392    ///     }
393    ///     id_upcast!();
394    /// }
395    ///
396    /// // Define a new allocator.
397    /// let bump = bumpalo::Bump::new();
398    /// let hasher = RandomState::new();
399    /// // Create a new IdHashMap with capacity and hasher using the allocator.
400    /// let map: IdHashMap<Item, _, &bumpalo::Bump> =
401    ///     IdHashMap::with_capacity_and_hasher_in(10, hasher, &bump);
402    /// assert!(map.capacity() >= 10);
403    /// assert!(map.is_empty());
404    /// # }
405    /// ```
406    pub fn with_capacity_and_hasher_in(
407        capacity: usize,
408        hasher: S,
409        alloc: A,
410    ) -> Self {
411        Self {
412            items: ItemSet::with_capacity_in(capacity, alloc.clone()),
413            tables: IdHashMapTables::with_capacity_and_hasher_in(
414                capacity, hasher, alloc,
415            ),
416        }
417    }
418}
419
420impl<T: IdHashItem, S: Clone + BuildHasher, A: Allocator> IdHashMap<T, S, A> {
421    #[cfg(feature = "daft")]
422    pub(crate) fn hasher(&self) -> &S {
423        self.tables.hasher()
424    }
425
426    /// Returns the allocator.
427    ///
428    /// Requires the `allocator-api2` feature to be enabled.
429    ///
430    /// # Examples
431    ///
432    /// Using the [`bumpalo`](https://docs.rs/bumpalo) allocator:
433    ///
434    /// ```
435    /// # #[cfg(all(feature = "default-hasher", feature = "allocator-api2"))] {
436    /// use iddqd::{IdHashMap, IdHashItem, id_upcast};
437    /// # use iddqd_test_utils::bumpalo;
438    ///
439    /// #[derive(Debug, PartialEq, Eq, Hash)]
440    /// struct Item {
441    ///     id: String,
442    ///     value: u32,
443    /// }
444    ///
445    /// impl IdHashItem for Item {
446    ///     type Key<'a> = &'a str;
447    ///     fn key(&self) -> Self::Key<'_> { &self.id }
448    ///     id_upcast!();
449    /// }
450    ///
451    /// // Define a new allocator.
452    /// let bump = bumpalo::Bump::new();
453    /// // Create a new IdHashMap using the allocator.
454    /// let map: IdHashMap<Item, _, &bumpalo::Bump> = IdHashMap::new_in(&bump);
455    /// let _allocator = map.allocator();
456    /// # }
457    /// ```
458    pub fn allocator(&self) -> &A {
459        self.items.allocator()
460    }
461
462    /// Returns the currently allocated capacity of the map.
463    ///
464    /// # Examples
465    ///
466    /// ```
467    /// # #[cfg(feature = "default-hasher")] {
468    /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
469    ///
470    /// #[derive(Debug, PartialEq, Eq, Hash)]
471    /// struct Item {
472    ///     id: String,
473    ///     value: u32,
474    /// }
475    ///
476    /// impl IdHashItem for Item {
477    ///     type Key<'a> = &'a str;
478    ///     fn key(&self) -> Self::Key<'_> {
479    ///         &self.id
480    ///     }
481    ///     id_upcast!();
482    /// }
483    ///
484    /// let map: IdHashMap<Item> = IdHashMap::with_capacity(10);
485    /// assert!(map.capacity() >= 10);
486    /// # }
487    /// ```
488    pub fn capacity(&self) -> usize {
489        // items and tables.capacity might theoretically diverge: use
490        // items.capacity.
491        self.items.capacity()
492    }
493
494    /// Returns true if the map is empty.
495    ///
496    /// # Examples
497    ///
498    /// ```
499    /// # #[cfg(feature = "default-hasher")] {
500    /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
501    ///
502    /// #[derive(Debug, PartialEq, Eq, Hash)]
503    /// struct Item {
504    ///     id: String,
505    ///     value: u32,
506    /// }
507    ///
508    /// impl IdHashItem for Item {
509    ///     type Key<'a> = &'a str;
510    ///     fn key(&self) -> Self::Key<'_> {
511    ///         &self.id
512    ///     }
513    ///     id_upcast!();
514    /// }
515    ///
516    /// let mut map = IdHashMap::new();
517    /// assert!(map.is_empty());
518    ///
519    /// map.insert_unique(Item { id: "foo".to_string(), value: 42 }).unwrap();
520    /// assert!(!map.is_empty());
521    /// # }
522    /// ```
523    #[inline]
524    pub fn is_empty(&self) -> bool {
525        self.items.is_empty()
526    }
527
528    /// Returns the number of items in the map.
529    ///
530    /// # Examples
531    ///
532    /// ```
533    /// # #[cfg(feature = "default-hasher")] {
534    /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
535    ///
536    /// #[derive(Debug, PartialEq, Eq, Hash)]
537    /// struct Item {
538    ///     id: String,
539    ///     value: u32,
540    /// }
541    ///
542    /// impl IdHashItem for Item {
543    ///     type Key<'a> = &'a str;
544    ///     fn key(&self) -> Self::Key<'_> {
545    ///         &self.id
546    ///     }
547    ///     id_upcast!();
548    /// }
549    ///
550    /// let mut map = IdHashMap::new();
551    /// assert_eq!(map.len(), 0);
552    ///
553    /// map.insert_unique(Item { id: "foo".to_string(), value: 42 }).unwrap();
554    /// assert_eq!(map.len(), 1);
555    ///
556    /// map.insert_unique(Item { id: "bar".to_string(), value: 20 }).unwrap();
557    /// assert_eq!(map.len(), 2);
558    /// # }
559    /// ```
560    #[inline]
561    pub fn len(&self) -> usize {
562        self.items.len()
563    }
564
565    /// Clears the map, removing all items.
566    ///
567    /// # Examples
568    ///
569    /// ```
570    /// # #[cfg(feature = "default-hasher")] {
571    /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
572    ///
573    /// #[derive(Debug, PartialEq, Eq, Hash)]
574    /// struct Item {
575    ///     id: String,
576    ///     value: u32,
577    /// }
578    ///
579    /// impl IdHashItem for Item {
580    ///     type Key<'a> = &'a str;
581    ///     fn key(&self) -> Self::Key<'_> {
582    ///         &self.id
583    ///     }
584    ///     id_upcast!();
585    /// }
586    ///
587    /// let mut map = IdHashMap::new();
588    /// map.insert_unique(Item { id: "foo".to_string(), value: 42 }).unwrap();
589    /// map.insert_unique(Item { id: "bar".to_string(), value: 20 }).unwrap();
590    /// assert_eq!(map.len(), 2);
591    ///
592    /// map.clear();
593    /// assert!(map.is_empty());
594    /// assert_eq!(map.len(), 0);
595    /// # }
596    /// ```
597    pub fn clear(&mut self) {
598        self.items.clear();
599        self.tables.key_to_item.clear();
600    }
601
602    /// Reserves capacity for at least `additional` more elements to be inserted
603    /// in the `IdHashMap`. The collection may reserve more space to
604    /// speculatively avoid frequent reallocations. After calling `reserve`,
605    /// capacity will be greater than or equal to `self.len() + additional`.
606    /// Does nothing if capacity is already sufficient.
607    ///
608    /// # Panics
609    ///
610    /// Panics if the new capacity overflows [`isize::MAX`] bytes, and
611    /// [`abort`]s the program in case of an allocation error. Use
612    /// [`try_reserve`](Self::try_reserve) instead if you want to handle memory
613    /// allocation failure.
614    ///
615    /// [`isize::MAX`]: https://doc.rust-lang.org/std/primitive.isize.html
616    /// [`abort`]: https://doc.rust-lang.org/alloc/alloc/fn.handle_alloc_error.html
617    ///
618    /// # Examples
619    ///
620    /// ```
621    /// # #[cfg(feature = "default-hasher")] {
622    /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
623    ///
624    /// #[derive(Debug, PartialEq, Eq, Hash)]
625    /// struct Item {
626    ///     id: String,
627    ///     value: u32,
628    /// }
629    ///
630    /// impl IdHashItem for Item {
631    ///     type Key<'a> = &'a str;
632    ///     fn key(&self) -> Self::Key<'_> {
633    ///         &self.id
634    ///     }
635    ///     id_upcast!();
636    /// }
637    ///
638    /// let mut map: IdHashMap<Item> = IdHashMap::new();
639    /// map.reserve(100);
640    /// assert!(map.capacity() >= 100);
641    /// # }
642    /// ```
643    pub fn reserve(&mut self, additional: usize) {
644        self.items.reserve(additional);
645        let items = &self.items;
646        let state = &self.tables.state;
647        self.tables
648            .key_to_item
649            .reserve(additional, |ix| state.hash_one(items[*ix].key()));
650    }
651
652    /// Tries to reserve capacity for at least `additional` more elements to be
653    /// inserted in the `IdHashMap`. The collection may reserve more space to
654    /// speculatively avoid frequent reallocations. After calling `try_reserve`,
655    /// capacity will be greater than or equal to `self.len() + additional` if
656    /// it returns `Ok(())`. Does nothing if capacity is already sufficient.
657    ///
658    /// # Errors
659    ///
660    /// If the capacity overflows, or the allocator reports a failure, then an
661    /// error is returned.
662    ///
663    /// # Notes
664    ///
665    /// If reservation fails partway through, some internal structures may have
666    /// already increased their capacity. The map remains in a valid state but
667    /// may have uneven capacities across its internal structures.
668    ///
669    /// # Examples
670    ///
671    /// ```
672    /// # #[cfg(feature = "default-hasher")] {
673    /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
674    ///
675    /// #[derive(Debug, PartialEq, Eq, Hash)]
676    /// struct Item {
677    ///     id: String,
678    ///     value: u32,
679    /// }
680    ///
681    /// impl IdHashItem for Item {
682    ///     type Key<'a> = &'a str;
683    ///     fn key(&self) -> Self::Key<'_> {
684    ///         &self.id
685    ///     }
686    ///     id_upcast!();
687    /// }
688    ///
689    /// let mut map: IdHashMap<Item> = IdHashMap::new();
690    /// map.try_reserve(100).expect("allocation should succeed");
691    /// assert!(map.capacity() >= 100);
692    /// # }
693    /// ```
694    pub fn try_reserve(
695        &mut self,
696        additional: usize,
697    ) -> Result<(), crate::errors::TryReserveError> {
698        self.items.try_reserve(additional)?;
699        let items = &self.items;
700        let state = &self.tables.state;
701        self.tables
702            .key_to_item
703            .try_reserve(additional, |ix| state.hash_one(items[*ix].key()))
704            .map_err(crate::errors::TryReserveError::from_hashbrown)?;
705        Ok(())
706    }
707
708    /// Shrinks the capacity of the map as much as possible. It will drop
709    /// down as much as possible while maintaining the internal rules
710    /// and possibly leaving some space in accordance with the resize policy.
711    ///
712    /// # Examples
713    ///
714    /// ```
715    /// # #[cfg(feature = "default-hasher")] {
716    /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
717    ///
718    /// #[derive(Debug, PartialEq, Eq, Hash)]
719    /// struct Item {
720    ///     id: String,
721    ///     value: u32,
722    /// }
723    ///
724    /// impl IdHashItem for Item {
725    ///     type Key<'a> = &'a str;
726    ///     fn key(&self) -> Self::Key<'_> {
727    ///         &self.id
728    ///     }
729    ///     id_upcast!();
730    /// }
731    ///
732    /// let mut map: IdHashMap<Item> = IdHashMap::with_capacity(100);
733    /// map.insert_unique(Item { id: "foo".to_string(), value: 1 }).unwrap();
734    /// map.insert_unique(Item { id: "bar".to_string(), value: 2 }).unwrap();
735    /// assert!(map.capacity() >= 100);
736    /// map.shrink_to_fit();
737    /// assert!(map.capacity() >= 2);
738    /// # }
739    /// ```
740    pub fn shrink_to_fit(&mut self) {
741        let remap = self.items.shrink_to_fit();
742        if !remap.is_identity() {
743            self.tables.key_to_item.remap_indexes(&remap);
744        }
745        let items = &self.items;
746        let state = &self.tables.state;
747        self.tables
748            .key_to_item
749            .shrink_to_fit(|ix| state.hash_one(items[*ix].key()));
750    }
751
752    /// Shrinks the capacity of the map with a lower limit. It will drop
753    /// down no lower than the supplied limit while maintaining the internal
754    /// rules and possibly leaving some space in accordance with the resize
755    /// policy.
756    ///
757    /// If the current capacity is less than the lower limit, this is a no-op.
758    ///
759    /// # Examples
760    ///
761    /// ```
762    /// # #[cfg(feature = "default-hasher")] {
763    /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
764    ///
765    /// #[derive(Debug, PartialEq, Eq, Hash)]
766    /// struct Item {
767    ///     id: String,
768    ///     value: u32,
769    /// }
770    ///
771    /// impl IdHashItem for Item {
772    ///     type Key<'a> = &'a str;
773    ///     fn key(&self) -> Self::Key<'_> {
774    ///         &self.id
775    ///     }
776    ///     id_upcast!();
777    /// }
778    ///
779    /// let mut map: IdHashMap<Item> = IdHashMap::with_capacity(100);
780    /// map.insert_unique(Item { id: "foo".to_string(), value: 1 }).unwrap();
781    /// map.insert_unique(Item { id: "bar".to_string(), value: 2 }).unwrap();
782    /// assert!(map.capacity() >= 100);
783    /// map.shrink_to(10);
784    /// assert!(map.capacity() >= 10);
785    /// map.shrink_to(0);
786    /// assert!(map.capacity() >= 2);
787    /// # }
788    /// ```
789    pub fn shrink_to(&mut self, min_capacity: usize) {
790        let remap = self.items.shrink_to(min_capacity);
791        if !remap.is_identity() {
792            self.tables.key_to_item.remap_indexes(&remap);
793        }
794        let items = &self.items;
795        let state = &self.tables.state;
796        self.tables
797            .key_to_item
798            .shrink_to(min_capacity, |ix| state.hash_one(items[*ix].key()));
799    }
800
801    /// Iterates over the items in the map.
802    ///
803    /// Similar to [`HashMap`], the iteration order is arbitrary and not
804    /// guaranteed to be stable.
805    ///
806    /// # Examples
807    ///
808    /// ```
809    /// # #[cfg(feature = "default-hasher")] {
810    /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
811    ///
812    /// #[derive(Debug, PartialEq, Eq, Hash)]
813    /// struct Item {
814    ///     id: String,
815    ///     value: u32,
816    /// }
817    ///
818    /// impl IdHashItem for Item {
819    ///     type Key<'a> = &'a str;
820    ///     fn key(&self) -> Self::Key<'_> {
821    ///         &self.id
822    ///     }
823    ///     id_upcast!();
824    /// }
825    ///
826    /// let mut map = IdHashMap::new();
827    /// map.insert_unique(Item { id: "foo".to_string(), value: 42 }).unwrap();
828    /// map.insert_unique(Item { id: "bar".to_string(), value: 20 }).unwrap();
829    ///
830    /// let mut values: Vec<u32> = map.iter().map(|item| item.value).collect();
831    /// values.sort();
832    /// assert_eq!(values, vec![20, 42]);
833    /// # }
834    /// ```
835    ///
836    /// [`HashMap`]: std::collections::HashMap
837    #[inline]
838    pub fn iter(&self) -> Iter<'_, T> {
839        Iter::new(&self.items)
840    }
841
842    /// Iterates over the items in the map, allowing for mutation.
843    ///
844    /// Similar to [`HashMap`], the iteration order is arbitrary and not
845    /// guaranteed to be stable.
846    ///
847    /// # Examples
848    ///
849    /// ```
850    /// # #[cfg(feature = "default-hasher")] {
851    /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
852    ///
853    /// #[derive(Debug, PartialEq, Eq, Hash)]
854    /// struct Item {
855    ///     id: String,
856    ///     value: u32,
857    /// }
858    ///
859    /// impl IdHashItem for Item {
860    ///     type Key<'a> = &'a str;
861    ///     fn key(&self) -> Self::Key<'_> {
862    ///         &self.id
863    ///     }
864    ///     id_upcast!();
865    /// }
866    ///
867    /// let mut map = IdHashMap::new();
868    /// map.insert_unique(Item { id: "foo".to_string(), value: 42 }).unwrap();
869    /// map.insert_unique(Item { id: "bar".to_string(), value: 20 }).unwrap();
870    ///
871    /// for mut item in map.iter_mut() {
872    ///     item.value *= 2;
873    /// }
874    ///
875    /// assert_eq!(map.get("foo").unwrap().value, 84);
876    /// assert_eq!(map.get("bar").unwrap().value, 40);
877    /// # }
878    /// ```
879    ///
880    /// [`HashMap`]: std::collections::HashMap
881    #[inline]
882    pub fn iter_mut(&mut self) -> IterMut<'_, T, S, A> {
883        IterMut::new(&self.tables, &mut self.items)
884    }
885
886    /// Checks general invariants of the map.
887    ///
888    /// The code below always upholds these invariants, but it's useful to have
889    /// an explicit check for tests.
890    #[doc(hidden)]
891    pub fn validate(
892        &self,
893        compactness: ValidateCompact,
894    ) -> Result<(), ValidationError>
895    where
896        T: fmt::Debug,
897    {
898        self.items.validate(compactness)?;
899        self.tables.validate(self.len(), compactness)?;
900
901        // Check that the indexes are all correct.
902        for (ix, item) in self.items.iter() {
903            let key = item.key();
904            let Some(ix1) = self.find_index(&key) else {
905                return Err(ValidationError::general(format!(
906                    "item at index {ix} has no key1 index"
907                )));
908            };
909
910            if ix1 != ix {
911                return Err(ValidationError::General(format!(
912                    "item at index {ix} has mismatched indexes: ix1: {ix1}",
913                )));
914            }
915        }
916
917        Ok(())
918    }
919
920    /// Inserts a value into the map, removing and returning the conflicting
921    /// item, if any.
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    ///
945    /// // First insertion returns None
946    /// let old = map.insert_overwrite(Item { id: "foo".to_string(), value: 42 });
947    /// assert!(old.is_none());
948    ///
949    /// // Second insertion with same key returns the old value
950    /// let old = map.insert_overwrite(Item { id: "foo".to_string(), value: 100 });
951    /// assert_eq!(old.unwrap().value, 42);
952    /// assert_eq!(map.get("foo").unwrap().value, 100);
953    /// # }
954    /// ```
955    #[doc(alias = "insert")]
956    pub fn insert_overwrite(&mut self, value: T) -> Option<T> {
957        // Go through the entry API so all user code is called before any table
958        // mutation. A panic in user code therefore leaves the map in its
959        // pre-call state.
960        //
961        // We use `vacant.insert_entry` rather than `vacant.insert` to avoid
962        // creating a `RefMut`, which would (unnecessarily) re-hash the key
963        // after the mutation when that `RefMut` is created.
964        match self.entry(value.key()) {
965            Entry::Occupied(mut occupied) => Some(occupied.insert(value)),
966            Entry::Vacant(vacant) => {
967                vacant.insert_entry(value);
968                None
969            }
970        }
971    }
972
973    /// Inserts a value into the set, returning an error if any duplicates were
974    /// added.
975    ///
976    /// # Examples
977    ///
978    /// ```
979    /// # #[cfg(feature = "default-hasher")] {
980    /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
981    ///
982    /// #[derive(Debug, PartialEq, Eq, Hash)]
983    /// struct Item {
984    ///     id: String,
985    ///     value: u32,
986    /// }
987    ///
988    /// impl IdHashItem for Item {
989    ///     type Key<'a> = &'a str;
990    ///     fn key(&self) -> Self::Key<'_> {
991    ///         &self.id
992    ///     }
993    ///     id_upcast!();
994    /// }
995    ///
996    /// let mut map = IdHashMap::new();
997    ///
998    /// // First insertion succeeds
999    /// assert!(
1000    ///     map.insert_unique(Item { id: "foo".to_string(), value: 42 }).is_ok()
1001    /// );
1002    ///
1003    /// // Second insertion with different key succeeds
1004    /// assert!(
1005    ///     map.insert_unique(Item { id: "bar".to_string(), value: 20 }).is_ok()
1006    /// );
1007    ///
1008    /// // Third insertion with duplicate key fails
1009    /// assert!(
1010    ///     map.insert_unique(Item { id: "foo".to_string(), value: 100 }).is_err()
1011    /// );
1012    /// # }
1013    /// ```
1014    pub fn insert_unique(
1015        &mut self,
1016        value: T,
1017    ) -> Result<(), DuplicateItem<T, &T>> {
1018        let _ = self.insert_unique_impl(value)?;
1019        Ok(())
1020    }
1021
1022    /// Returns true if the map contains the given key.
1023    ///
1024    /// # Examples
1025    ///
1026    /// ```
1027    /// # #[cfg(feature = "default-hasher")] {
1028    /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
1029    ///
1030    /// #[derive(Debug, PartialEq, Eq, Hash)]
1031    /// struct Item {
1032    ///     id: String,
1033    ///     value: u32,
1034    /// }
1035    ///
1036    /// impl IdHashItem for Item {
1037    ///     type Key<'a> = &'a str;
1038    ///     fn key(&self) -> Self::Key<'_> {
1039    ///         &self.id
1040    ///     }
1041    ///     id_upcast!();
1042    /// }
1043    ///
1044    /// let mut map = IdHashMap::new();
1045    /// map.insert_unique(Item { id: "foo".to_string(), value: 42 }).unwrap();
1046    ///
1047    /// assert!(map.contains_key("foo"));
1048    /// assert!(!map.contains_key("bar"));
1049    /// # }
1050    /// ```
1051    pub fn contains_key<'a, Q>(&'a self, key1: &Q) -> bool
1052    where
1053        Q: ?Sized + Hash + Equivalent<T::Key<'a>>,
1054    {
1055        self.find_index(key1).is_some()
1056    }
1057
1058    /// Gets a reference to the value associated with the given key.
1059    ///
1060    /// # Examples
1061    ///
1062    /// ```
1063    /// # #[cfg(feature = "default-hasher")] {
1064    /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
1065    ///
1066    /// #[derive(Debug, PartialEq, Eq, Hash)]
1067    /// struct Item {
1068    ///     id: String,
1069    ///     value: u32,
1070    /// }
1071    ///
1072    /// impl IdHashItem for Item {
1073    ///     type Key<'a> = &'a str;
1074    ///     fn key(&self) -> Self::Key<'_> {
1075    ///         &self.id
1076    ///     }
1077    ///     id_upcast!();
1078    /// }
1079    ///
1080    /// let mut map = IdHashMap::new();
1081    /// map.insert_unique(Item { id: "foo".to_string(), value: 42 }).unwrap();
1082    ///
1083    /// assert_eq!(map.get("foo").unwrap().value, 42);
1084    /// assert!(map.get("bar").is_none());
1085    /// # }
1086    /// ```
1087    pub fn get<'a, Q>(&'a self, key: &Q) -> Option<&'a T>
1088    where
1089        Q: ?Sized + Hash + Equivalent<T::Key<'a>>,
1090    {
1091        self.find_index(key).map(|ix| &self.items[ix])
1092    }
1093
1094    /// Gets a mutable reference to the value associated with the given key.
1095    ///
1096    /// # Examples
1097    ///
1098    /// ```
1099    /// # #[cfg(feature = "default-hasher")] {
1100    /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
1101    ///
1102    /// #[derive(Debug, PartialEq, Eq, Hash)]
1103    /// struct Item {
1104    ///     id: String,
1105    ///     value: u32,
1106    /// }
1107    ///
1108    /// impl IdHashItem for Item {
1109    ///     type Key<'a> = &'a str;
1110    ///     fn key(&self) -> Self::Key<'_> {
1111    ///         &self.id
1112    ///     }
1113    ///     id_upcast!();
1114    /// }
1115    ///
1116    /// let mut map = IdHashMap::new();
1117    /// map.insert_unique(Item { id: "foo".to_string(), value: 42 }).unwrap();
1118    ///
1119    /// if let Some(mut item) = map.get_mut("foo") {
1120    ///     item.value = 100;
1121    /// }
1122    ///
1123    /// assert_eq!(map.get("foo").unwrap().value, 100);
1124    /// assert!(map.get_mut("bar").is_none());
1125    /// # }
1126    /// ```
1127    pub fn get_mut<'a, Q>(&'a mut self, key: &Q) -> Option<RefMut<'a, T, S>>
1128    where
1129        Q: ?Sized + Hash + Equivalent<T::Key<'a>>,
1130    {
1131        let (dormant_map, index) = {
1132            let (map, dormant_map) = DormantMutRef::new(self);
1133            let index = map.find_index(key)?;
1134            (dormant_map, index)
1135        };
1136
1137        // SAFETY: `map` is not used after this point.
1138        let awakened_map = unsafe { dormant_map.awaken() };
1139        let item = &mut awakened_map.items[index];
1140        let state = awakened_map.tables.state.clone();
1141        let hashes = awakened_map.tables.make_hash(item);
1142        Some(RefMut::new(state, hashes, item))
1143    }
1144
1145    /// Removes an item from the map by its key.
1146    ///
1147    /// # Examples
1148    ///
1149    /// ```
1150    /// # #[cfg(feature = "default-hasher")] {
1151    /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
1152    ///
1153    /// #[derive(Debug, PartialEq, Eq, Hash)]
1154    /// struct Item {
1155    ///     id: String,
1156    ///     value: u32,
1157    /// }
1158    ///
1159    /// impl IdHashItem for Item {
1160    ///     type Key<'a> = &'a str;
1161    ///     fn key(&self) -> Self::Key<'_> {
1162    ///         &self.id
1163    ///     }
1164    ///     id_upcast!();
1165    /// }
1166    ///
1167    /// let mut map = IdHashMap::new();
1168    /// map.insert_unique(Item { id: "foo".to_string(), value: 42 }).unwrap();
1169    ///
1170    /// let removed = map.remove("foo");
1171    /// assert_eq!(removed.unwrap().value, 42);
1172    /// assert!(map.is_empty());
1173    ///
1174    /// // Removing non-existent key returns None
1175    /// assert!(map.remove("bar").is_none());
1176    /// # }
1177    /// ```
1178    pub fn remove<'a, Q>(&'a mut self, key: &Q) -> Option<T>
1179    where
1180        Q: ?Sized + Hash + Equivalent<T::Key<'a>>,
1181    {
1182        let (dormant_map, remove_index) = {
1183            let (map, dormant_map) = DormantMutRef::new(self);
1184            let remove_index = map.find_index(key)?;
1185            (dormant_map, remove_index)
1186        };
1187        // SAFETY: `map` is not used after this point.
1188        let awakened_map = unsafe { dormant_map.awaken() };
1189        awakened_map.remove_by_index(remove_index)
1190    }
1191
1192    /// Retrieves an entry by its key.
1193    ///
1194    /// Due to borrow checker limitations, this always accepts an owned key
1195    /// rather than a borrowed form of it.
1196    ///
1197    /// # Examples
1198    ///
1199    /// ```
1200    /// # #[cfg(feature = "default-hasher")] {
1201    /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
1202    ///
1203    /// #[derive(Debug, PartialEq, Eq, Hash)]
1204    /// struct Item {
1205    ///     id: String,
1206    ///     value: u32,
1207    /// }
1208    ///
1209    /// impl IdHashItem for Item {
1210    ///     type Key<'a> = &'a str;
1211    ///     fn key(&self) -> Self::Key<'_> {
1212    ///         &self.id
1213    ///     }
1214    ///     id_upcast!();
1215    /// }
1216    ///
1217    /// let mut map = IdHashMap::new();
1218    ///
1219    /// // Use entry API for conditional insertion
1220    /// map.entry("foo").or_insert(Item { id: "foo".to_string(), value: 42 });
1221    /// map.entry("bar").or_insert(Item { id: "bar".to_string(), value: 20 });
1222    ///
1223    /// assert_eq!(map.len(), 2);
1224    /// # }
1225    /// ```
1226    pub fn entry<'a>(&'a mut self, key: T::Key<'_>) -> Entry<'a, T, S, A> {
1227        // Why does this always take an owned key? Well, it would seem like we
1228        // should be able to pass in any Q that is equivalent. That results in
1229        // *this* code compiling fine, but callers have trouble using it because
1230        // the borrow checker believes the keys are borrowed for the full 'a
1231        // rather than a shorter lifetime.
1232        //
1233        // By accepting owned keys, we can use the upcast functions to convert
1234        // them to a shorter lifetime (so this function accepts T::Key<'_>
1235        // rather than T::Key<'a>).
1236        //
1237        // Really, the solution here is to allow GATs to require covariant
1238        // parameters. If that were allowed, the borrow checker should be able
1239        // to figure out that keys don't need to be borrowed for the full 'a,
1240        // just for some shorter lifetime.
1241        let (map, dormant_map) = DormantMutRef::new(self);
1242        let key = T::upcast_key(key);
1243        {
1244            // index is explicitly typed to show that it has a trivial Drop impl
1245            // that doesn't capture anything from map.
1246            let index: Option<ItemIndex> = map.tables.key_to_item.find_index(
1247                &map.tables.state,
1248                &key,
1249                |index| map.items[index].key(),
1250            );
1251            if let Some(index) = index {
1252                drop(key);
1253                return Entry::Occupied(
1254                    // SAFETY: `map` is not used after this point.
1255                    unsafe { OccupiedEntry::new(dormant_map, index) },
1256                );
1257            }
1258        }
1259        let hash = map.make_key_hash(&key);
1260        Entry::Vacant(
1261            // SAFETY: `map` is not used after this point.
1262            unsafe { VacantEntry::new(dormant_map, hash) },
1263        )
1264    }
1265
1266    /// Retains only the elements specified by the predicate.
1267    ///
1268    /// In other words, remove all items `T` for which `f(RefMut<T>)` returns
1269    /// false. The elements are visited in an arbitrary order.
1270    ///
1271    /// # Examples
1272    ///
1273    /// ```
1274    /// # #[cfg(feature = "default-hasher")] {
1275    /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
1276    ///
1277    /// #[derive(Debug, PartialEq, Eq, Hash)]
1278    /// struct Item {
1279    ///     id: String,
1280    ///     value: u32,
1281    /// }
1282    ///
1283    /// impl IdHashItem for Item {
1284    ///     type Key<'a> = &'a str;
1285    ///
1286    ///     fn key(&self) -> Self::Key<'_> {
1287    ///         &self.id
1288    ///     }
1289    ///
1290    ///     id_upcast!();
1291    /// }
1292    ///
1293    /// let mut map = IdHashMap::new();
1294    /// map.insert_unique(Item { id: "foo".to_string(), value: 42 }).unwrap();
1295    /// map.insert_unique(Item { id: "bar".to_string(), value: 20 }).unwrap();
1296    /// map.insert_unique(Item { id: "baz".to_string(), value: 99 }).unwrap();
1297    ///
1298    /// // Retain only items where value is greater than 30
1299    /// map.retain(|item| item.value > 30);
1300    ///
1301    /// assert_eq!(map.len(), 2);
1302    /// assert_eq!(map.get("foo").unwrap().value, 42);
1303    /// assert_eq!(map.get("baz").unwrap().value, 99);
1304    /// assert!(map.get("bar").is_none());
1305    /// # }
1306    /// ```
1307    pub fn retain<'a, F>(&'a mut self, mut f: F)
1308    where
1309        F: FnMut(RefMut<'a, T, S>) -> bool,
1310    {
1311        let hash_state = self.tables.state.clone();
1312        let (_, mut dormant_items) = DormantMutRef::new(&mut self.items);
1313
1314        self.tables.key_to_item.retain(|index| {
1315            let (item, dormant_items) = {
1316                // SAFETY: All uses of `items` ended in the previous iteration.
1317                let items = unsafe { dormant_items.reborrow() };
1318                let (items, dormant_items) = DormantMutRef::new(items);
1319                let item: &'a mut T = items
1320                    .get_mut(index)
1321                    .expect("all indexes are present in self.items");
1322                (item, dormant_items)
1323            };
1324
1325            let (hash, dormant_item) = {
1326                let (item, dormant_item): (&'a mut T, _) =
1327                    DormantMutRef::new(item);
1328                // Use T::key(item) rather than item.key() to force the key
1329                // trait function to be called for T rather than &mut T.
1330                let key = T::key(item);
1331                let hash = hash_state.hash_one(key);
1332                (MapHash::new(hash), dormant_item)
1333            };
1334
1335            let retain = {
1336                // SAFETY: The original item is no longer used after the second
1337                // block above. dormant_items, from which item is derived, is
1338                // currently dormant.
1339                let item = unsafe { dormant_item.awaken() };
1340
1341                let ref_mut = RefMut::new(hash_state.clone(), hash, item);
1342                f(ref_mut)
1343            };
1344
1345            if retain {
1346                true
1347            } else {
1348                // SAFETY: The original items is no longer used after the first
1349                // block above, and item + dormant item have been used above.
1350                let items = unsafe { dormant_items.awaken() };
1351                items.remove(index);
1352                false
1353            }
1354        });
1355    }
1356
1357    fn find_index<'a, Q>(&'a self, k: &Q) -> Option<ItemIndex>
1358    where
1359        Q: Hash + Equivalent<T::Key<'a>> + ?Sized,
1360    {
1361        self.tables
1362            .key_to_item
1363            .find_index(&self.tables.state, k, |index| self.items[index].key())
1364    }
1365
1366    fn make_hash(&self, item: &T) -> MapHash {
1367        self.tables.make_hash(item)
1368    }
1369
1370    fn make_key_hash(&self, key: &T::Key<'_>) -> MapHash {
1371        self.tables.make_key_hash::<T>(key)
1372    }
1373
1374    pub(super) fn get_by_index(&self, index: ItemIndex) -> Option<&T> {
1375        self.items.get(index)
1376    }
1377
1378    pub(super) fn get_by_index_mut(
1379        &mut self,
1380        index: ItemIndex,
1381    ) -> Option<RefMut<'_, T, S>> {
1382        let state = self.tables.state.clone();
1383        let hashes = self.make_hash(&self.items[index]);
1384        let item = &mut self.items[index];
1385        Some(RefMut::new(state, hashes, item))
1386    }
1387
1388    pub(super) fn insert_unique_impl(
1389        &mut self,
1390        value: T,
1391    ) -> Result<ItemIndex, DuplicateItem<T, &T>> {
1392        let mut duplicates = BTreeSet::new();
1393
1394        // Check for duplicates *before* inserting the new item, because we
1395        // don't want to partially insert the new item and then have to roll
1396        // back.
1397        let key = value.key();
1398        let state = &self.tables.state;
1399
1400        let entry = match self
1401            .tables
1402            .key_to_item
1403            .entry(state, key, |index| self.items[index].key())
1404        {
1405            hash_table::Entry::Occupied(slot) => {
1406                duplicates.insert(*slot.get());
1407                None
1408            }
1409            hash_table::Entry::Vacant(slot) => Some(slot),
1410        };
1411
1412        if !duplicates.is_empty() {
1413            return Err(DuplicateItem::__internal_new(
1414                value,
1415                duplicates.iter().map(|ix| &self.items[*ix]).collect(),
1416            ));
1417        }
1418
1419        let next_index = self.items.assert_can_grow().insert(value);
1420        entry.unwrap().insert(next_index);
1421
1422        Ok(next_index)
1423    }
1424
1425    pub(super) fn remove_by_index(
1426        &mut self,
1427        remove_index: ItemIndex,
1428    ) -> Option<T> {
1429        // For panic safety, look up the table entry while `self.items` still
1430        // holds the value, then remove from the table and items in sequence.
1431        // hashbrown's `find_entry` is panic-safe under user-`Hash`/`Eq` panics
1432        // (the table is not mutated until `OccupiedEntry::remove` is called),
1433        // so a panic during the lookup leaves both items and the table
1434        // unmodified.
1435        let key = self.items.get(remove_index)?.key();
1436        let state = &self.tables.state;
1437        let Ok(item) =
1438            self.tables
1439                .key_to_item
1440                .find_entry(state, &key, |index| self.items[index].key())
1441        else {
1442            panic!("we just looked this item up");
1443        };
1444        // Drop the key so that `self.items` can be mutated below.
1445        drop(key);
1446        item.remove();
1447        Some(
1448            self.items
1449                .remove(remove_index)
1450                .expect("items[remove_index] was Occupied above"),
1451        )
1452    }
1453
1454    pub(super) fn replace_at_index(&mut self, index: ItemIndex, value: T) -> T {
1455        // We check the key before removing it, to avoid leaving the map in an
1456        // inconsistent state.
1457        let old_key =
1458            self.get_by_index(index).expect("index is known to be valid").key();
1459        if T::upcast_key(old_key) != value.key() {
1460            panic!(
1461                "must insert a value with \
1462                 the same key used to create the entry"
1463            );
1464        }
1465
1466        // Now that we know the key is the same, we can replace the value
1467        // directly without needing to tweak any tables.
1468        self.items.replace(index, value)
1469    }
1470}
1471
1472impl<'a, T, S: Clone + BuildHasher, A: Allocator> fmt::Debug
1473    for IdHashMap<T, S, A>
1474where
1475    T: IdHashItem + fmt::Debug,
1476    T::Key<'a>: fmt::Debug,
1477    T: 'a,
1478{
1479    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1480        let mut map = f.debug_map();
1481
1482        for item in self.iter() {
1483            let key = item.key();
1484
1485            // SAFETY:
1486            //
1487            // * Lifetime extension: for a type T and two lifetime params 'a and
1488            //   'b, T<'a> and T<'b> aren't guaranteed to have the same layout,
1489            //   but (a) that is true today and (b) it would be shocking and
1490            //   break half the Rust ecosystem if that were to change in the
1491            //   future.
1492            // * We only use key within the scope of this block before immediately
1493            //   dropping it. In particular, map.entry calls key.fmt() without
1494            //   holding a reference to it.
1495            let key: T::Key<'a> =
1496                unsafe { core::mem::transmute::<T::Key<'_>, T::Key<'a>>(key) };
1497
1498            map.entry(&key, item);
1499        }
1500        map.finish()
1501    }
1502}
1503
1504impl<T: IdHashItem + PartialEq, S: Clone + BuildHasher, A: Allocator> PartialEq
1505    for IdHashMap<T, S, A>
1506{
1507    fn eq(&self, other: &Self) -> bool {
1508        // Implementing PartialEq for IdHashMap is tricky because IdHashMap is
1509        // not semantically like an IndexMap: two maps are equivalent even if
1510        // their items are in a different order. In other words, any permutation
1511        // of items is equivalent.
1512        //
1513        // We also can't sort the items because they're not necessarily Ord.
1514        //
1515        // So we write a custom equality check that checks that each key in one
1516        // map points to the same item as in the other map.
1517
1518        if self.items.len() != other.items.len() {
1519            return false;
1520        }
1521
1522        // Walk over all the items in the first map and check that they point to
1523        // the same item in the second map.
1524        for item in self.items.values() {
1525            let k1 = item.key();
1526
1527            // Check that the indexes are the same in the other map.
1528            let Some(other_ix) = other.find_index(&k1) else {
1529                return false;
1530            };
1531
1532            // Check that the other map's item is the same as this map's
1533            // item. (This is what we use the `PartialEq` bound on T for.)
1534            //
1535            // Because we've checked that other_ix is Some, we know that it is
1536            // valid and points to the expected item.
1537            let other_item = &other.items[other_ix];
1538            if item != other_item {
1539                return false;
1540            }
1541        }
1542
1543        true
1544    }
1545}
1546
1547// The Eq bound on T ensures that the TriHashMap forms an equivalence class.
1548impl<T: IdHashItem + Eq, S: Clone + BuildHasher, A: Allocator> Eq
1549    for IdHashMap<T, S, A>
1550{
1551}
1552
1553/// The `Extend` implementation overwrites duplicates. In the future, there will
1554/// also be an `extend_unique` method that will return an error.
1555///
1556/// # Examples
1557///
1558/// ```
1559/// # #[cfg(feature = "default-hasher")] {
1560/// use iddqd::{IdHashItem, IdHashMap, id_upcast};
1561///
1562/// #[derive(Debug, PartialEq, Eq, Hash)]
1563/// struct Item {
1564///     id: String,
1565///     value: u32,
1566/// }
1567///
1568/// impl IdHashItem for Item {
1569///     type Key<'a> = &'a str;
1570///     fn key(&self) -> Self::Key<'_> {
1571///         &self.id
1572///     }
1573///     id_upcast!();
1574/// }
1575///
1576/// let mut map = IdHashMap::new();
1577/// map.insert_unique(Item { id: "foo".to_string(), value: 42 }).unwrap();
1578///
1579/// let new_items = vec![
1580///     Item { id: "foo".to_string(), value: 100 }, // overwrites existing
1581///     Item { id: "bar".to_string(), value: 20 },  // new item
1582/// ];
1583///
1584/// map.extend(new_items);
1585/// assert_eq!(map.len(), 2);
1586/// assert_eq!(map.get("foo").unwrap().value, 100); // overwritten
1587/// assert_eq!(map.get("bar").unwrap().value, 20); // new
1588///
1589/// # }
1590/// ```
1591impl<T: IdHashItem, S: Clone + BuildHasher, A: Allocator> Extend<T>
1592    for IdHashMap<T, S, A>
1593{
1594    fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
1595        // Keys may already be present in the map, or multiple times in the
1596        // iterator. Reserve the entire hint lower bound if the map is empty.
1597        // Otherwise reserve half the hint (rounded up), so the map will only
1598        // resize twice in the worst case.
1599        let iter = iter.into_iter();
1600        let reserve = if self.is_empty() {
1601            iter.size_hint().0
1602        } else {
1603            iter.size_hint().0.div_ceil(2)
1604        };
1605        self.reserve(reserve);
1606        for item in iter {
1607            self.insert_overwrite(item);
1608        }
1609    }
1610}
1611
1612impl<'a, T: IdHashItem, S: Clone + BuildHasher, A: Allocator> IntoIterator
1613    for &'a IdHashMap<T, S, A>
1614{
1615    type Item = &'a T;
1616    type IntoIter = Iter<'a, T>;
1617
1618    /// Creates an iterator over references to the items in the map.
1619    ///
1620    /// # Examples
1621    ///
1622    /// ```
1623    /// # #[cfg(feature = "default-hasher")] {
1624    /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
1625    ///
1626    /// #[derive(Debug, PartialEq, Eq, Hash)]
1627    /// struct Item {
1628    ///     id: String,
1629    ///     value: u32,
1630    /// }
1631    ///
1632    /// impl IdHashItem for Item {
1633    ///     type Key<'a> = &'a str;
1634    ///     fn key(&self) -> Self::Key<'_> {
1635    ///         &self.id
1636    ///     }
1637    ///     id_upcast!();
1638    /// }
1639    ///
1640    /// let mut map = IdHashMap::new();
1641    /// map.insert_unique(Item { id: "foo".to_string(), value: 42 }).unwrap();
1642    /// map.insert_unique(Item { id: "bar".to_string(), value: 20 }).unwrap();
1643    ///
1644    /// let mut values: Vec<u32> =
1645    ///     (&map).into_iter().map(|item| item.value).collect();
1646    /// values.sort();
1647    /// assert_eq!(values, vec![20, 42]);
1648    /// # }
1649    /// ```
1650    #[inline]
1651    fn into_iter(self) -> Self::IntoIter {
1652        self.iter()
1653    }
1654}
1655
1656impl<'a, T: IdHashItem, S: Clone + BuildHasher, A: Allocator> IntoIterator
1657    for &'a mut IdHashMap<T, S, A>
1658{
1659    type Item = RefMut<'a, T, S>;
1660    type IntoIter = IterMut<'a, T, S, A>;
1661
1662    /// Creates an iterator over mutable references to the items in the map.
1663    ///
1664    /// # Examples
1665    ///
1666    /// ```
1667    /// # #[cfg(feature = "default-hasher")] {
1668    /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
1669    ///
1670    /// #[derive(Debug, PartialEq, Eq, Hash)]
1671    /// struct Item {
1672    ///     id: String,
1673    ///     value: u32,
1674    /// }
1675    ///
1676    /// impl IdHashItem for Item {
1677    ///     type Key<'a> = &'a str;
1678    ///     fn key(&self) -> Self::Key<'_> {
1679    ///         &self.id
1680    ///     }
1681    ///     id_upcast!();
1682    /// }
1683    ///
1684    /// let mut map = IdHashMap::new();
1685    /// map.insert_unique(Item { id: "foo".to_string(), value: 42 }).unwrap();
1686    /// map.insert_unique(Item { id: "bar".to_string(), value: 20 }).unwrap();
1687    ///
1688    /// for mut item in &mut map {
1689    ///     item.value *= 2;
1690    /// }
1691    ///
1692    /// assert_eq!(map.get("foo").unwrap().value, 84);
1693    /// assert_eq!(map.get("bar").unwrap().value, 40);
1694    /// # }
1695    /// ```
1696    #[inline]
1697    fn into_iter(self) -> Self::IntoIter {
1698        self.iter_mut()
1699    }
1700}
1701
1702impl<T: IdHashItem, S: Clone + BuildHasher, A: Allocator> IntoIterator
1703    for IdHashMap<T, S, A>
1704{
1705    type Item = T;
1706    type IntoIter = IntoIter<T, A>;
1707
1708    /// Consumes the map and creates an iterator over the owned items.
1709    ///
1710    /// # Examples
1711    ///
1712    /// ```
1713    /// # #[cfg(feature = "default-hasher")] {
1714    /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
1715    ///
1716    /// #[derive(Debug, PartialEq, Eq, Hash)]
1717    /// struct Item {
1718    ///     id: String,
1719    ///     value: u32,
1720    /// }
1721    ///
1722    /// impl IdHashItem for Item {
1723    ///     type Key<'a> = &'a str;
1724    ///     fn key(&self) -> Self::Key<'_> {
1725    ///         &self.id
1726    ///     }
1727    ///     id_upcast!();
1728    /// }
1729    ///
1730    /// let mut map = IdHashMap::new();
1731    /// map.insert_unique(Item { id: "foo".to_string(), value: 42 }).unwrap();
1732    /// map.insert_unique(Item { id: "bar".to_string(), value: 20 }).unwrap();
1733    ///
1734    /// let mut values: Vec<u32> = map.into_iter().map(|item| item.value).collect();
1735    /// values.sort();
1736    /// assert_eq!(values, vec![20, 42]);
1737    /// # }
1738    /// ```
1739    #[inline]
1740    fn into_iter(self) -> Self::IntoIter {
1741        IntoIter::new(self.items)
1742    }
1743}
1744
1745/// The `FromIterator` implementation for `IdHashMap` overwrites duplicate
1746/// items.
1747///
1748/// # Examples
1749///
1750/// ```
1751/// # #[cfg(feature = "default-hasher")] {
1752/// use iddqd::{IdHashItem, IdHashMap, id_upcast};
1753///
1754/// #[derive(Debug, PartialEq, Eq, Hash)]
1755/// struct Item {
1756///     id: String,
1757///     value: u32,
1758/// }
1759///
1760/// impl IdHashItem for Item {
1761///     type Key<'a> = &'a str;
1762///     fn key(&self) -> Self::Key<'_> {
1763///         &self.id
1764///     }
1765///     id_upcast!();
1766/// }
1767///
1768/// let items = vec![
1769///     Item { id: "foo".to_string(), value: 42 },
1770///     Item { id: "bar".to_string(), value: 20 },
1771///     Item { id: "foo".to_string(), value: 100 }, // duplicate key, overwrites
1772/// ];
1773///
1774/// let map: IdHashMap<Item> = items.into_iter().collect();
1775/// assert_eq!(map.len(), 2);
1776/// assert_eq!(map.get("foo").unwrap().value, 100); // last value wins
1777/// assert_eq!(map.get("bar").unwrap().value, 20);
1778/// # }
1779/// ```
1780impl<T: IdHashItem, S: Default + Clone + BuildHasher, A: Allocator + Default>
1781    FromIterator<T> for IdHashMap<T, S, A>
1782{
1783    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
1784        let mut map = IdHashMap::default();
1785        for item in iter {
1786            map.insert_overwrite(item);
1787        }
1788        map
1789    }
1790}