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        hash_table,
14        item_set::ItemSet,
15        map_hash::MapHash,
16    },
17};
18use alloc::collections::BTreeSet;
19use core::{
20    fmt,
21    hash::{BuildHasher, Hash},
22};
23use equivalent::Equivalent;
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        // Clear the internal index before dropping items. This way, if a user
599        // `Drop` panics during `self.items.clear()`, `key_to_item` cannot retain
600        // indexes pointing to removed item slots.
601        self.tables.key_to_item.clear();
602        self.items.clear();
603    }
604
605    /// Reserves capacity for at least `additional` more elements to be inserted
606    /// in the `IdHashMap`. The collection may reserve more space to
607    /// speculatively avoid frequent reallocations. After calling `reserve`,
608    /// capacity will be greater than or equal to `self.len() + additional`.
609    /// Does nothing if capacity is already sufficient.
610    ///
611    /// # Panics
612    ///
613    /// Panics if the new capacity overflows [`isize::MAX`] bytes, and
614    /// [`abort`]s the program in case of an allocation error. Use
615    /// [`try_reserve`](Self::try_reserve) instead if you want to handle memory
616    /// allocation failure.
617    ///
618    /// [`isize::MAX`]: https://doc.rust-lang.org/std/primitive.isize.html
619    /// [`abort`]: https://doc.rust-lang.org/alloc/alloc/fn.handle_alloc_error.html
620    ///
621    /// # Examples
622    ///
623    /// ```
624    /// # #[cfg(feature = "default-hasher")] {
625    /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
626    ///
627    /// #[derive(Debug, PartialEq, Eq, Hash)]
628    /// struct Item {
629    ///     id: String,
630    ///     value: u32,
631    /// }
632    ///
633    /// impl IdHashItem for Item {
634    ///     type Key<'a> = &'a str;
635    ///     fn key(&self) -> Self::Key<'_> {
636    ///         &self.id
637    ///     }
638    ///     id_upcast!();
639    /// }
640    ///
641    /// let mut map: IdHashMap<Item> = IdHashMap::new();
642    /// map.reserve(100);
643    /// assert!(map.capacity() >= 100);
644    /// # }
645    /// ```
646    pub fn reserve(&mut self, additional: usize) {
647        self.items.reserve(additional);
648        self.tables.key_to_item.reserve(additional);
649    }
650
651    /// Tries to reserve capacity for at least `additional` more elements to be
652    /// inserted in the `IdHashMap`. The collection may reserve more space to
653    /// speculatively avoid frequent reallocations. After calling `try_reserve`,
654    /// capacity will be greater than or equal to `self.len() + additional` if
655    /// it returns `Ok(())`. Does nothing if capacity is already sufficient.
656    ///
657    /// # Errors
658    ///
659    /// If the capacity overflows, or the allocator reports a failure, then an
660    /// error is returned.
661    ///
662    /// # Notes
663    ///
664    /// If reservation fails partway through, some internal structures may have
665    /// already increased their capacity. The map remains in a valid state but
666    /// may have uneven capacities across its internal structures.
667    ///
668    /// # Examples
669    ///
670    /// ```
671    /// # #[cfg(feature = "default-hasher")] {
672    /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
673    ///
674    /// #[derive(Debug, PartialEq, Eq, Hash)]
675    /// struct Item {
676    ///     id: String,
677    ///     value: u32,
678    /// }
679    ///
680    /// impl IdHashItem for Item {
681    ///     type Key<'a> = &'a str;
682    ///     fn key(&self) -> Self::Key<'_> {
683    ///         &self.id
684    ///     }
685    ///     id_upcast!();
686    /// }
687    ///
688    /// let mut map: IdHashMap<Item> = IdHashMap::new();
689    /// map.try_reserve(100).expect("allocation should succeed");
690    /// assert!(map.capacity() >= 100);
691    /// # }
692    /// ```
693    pub fn try_reserve(
694        &mut self,
695        additional: usize,
696    ) -> Result<(), crate::errors::TryReserveError> {
697        self.items.try_reserve(additional)?;
698        self.tables
699            .key_to_item
700            .try_reserve(additional)
701            .map_err(crate::errors::TryReserveError::from_hashbrown)?;
702        Ok(())
703    }
704
705    /// Shrinks the capacity of the map as much as possible. It will drop
706    /// down as much as possible while maintaining the internal rules
707    /// and possibly leaving some space in accordance with the resize policy.
708    ///
709    /// # Examples
710    ///
711    /// ```
712    /// # #[cfg(feature = "default-hasher")] {
713    /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
714    ///
715    /// #[derive(Debug, PartialEq, Eq, Hash)]
716    /// struct Item {
717    ///     id: String,
718    ///     value: u32,
719    /// }
720    ///
721    /// impl IdHashItem for Item {
722    ///     type Key<'a> = &'a str;
723    ///     fn key(&self) -> Self::Key<'_> {
724    ///         &self.id
725    ///     }
726    ///     id_upcast!();
727    /// }
728    ///
729    /// let mut map: IdHashMap<Item> = IdHashMap::with_capacity(100);
730    /// map.insert_unique(Item { id: "foo".to_string(), value: 1 }).unwrap();
731    /// map.insert_unique(Item { id: "bar".to_string(), value: 2 }).unwrap();
732    /// assert!(map.capacity() >= 100);
733    /// map.shrink_to_fit();
734    /// assert!(map.capacity() >= 2);
735    /// # }
736    /// ```
737    pub fn shrink_to_fit(&mut self) {
738        // Sequence this carefully.
739        //
740        // * First, compact the item set. This does not allocate through A
741        //   (it allocates a small remap buffer through the global allocator),
742        //   and returns a remapper.
743        // * Then, remap the tables using the remapper.
744        // * Finally, shrink the capacities of the tables and items.
745        //
746        // An allocator panic during either capacity shrink leaves the tables
747        // and items already in sync, because remap has already been committed.
748        let remap = self.items.compact();
749        if !remap.is_identity() {
750            self.tables.key_to_item.remap_indexes(&remap);
751        }
752        self.items.shrink_capacity_to_fit();
753        self.tables.key_to_item.shrink_to_fit();
754    }
755
756    /// Shrinks the capacity of the map with a lower limit. It will drop
757    /// down no lower than the supplied limit while maintaining the internal
758    /// rules and possibly leaving some space in accordance with the resize
759    /// policy.
760    ///
761    /// If the current capacity is less than the lower limit, this is a no-op.
762    ///
763    /// # Examples
764    ///
765    /// ```
766    /// # #[cfg(feature = "default-hasher")] {
767    /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
768    ///
769    /// #[derive(Debug, PartialEq, Eq, Hash)]
770    /// struct Item {
771    ///     id: String,
772    ///     value: u32,
773    /// }
774    ///
775    /// impl IdHashItem for Item {
776    ///     type Key<'a> = &'a str;
777    ///     fn key(&self) -> Self::Key<'_> {
778    ///         &self.id
779    ///     }
780    ///     id_upcast!();
781    /// }
782    ///
783    /// let mut map: IdHashMap<Item> = IdHashMap::with_capacity(100);
784    /// map.insert_unique(Item { id: "foo".to_string(), value: 1 }).unwrap();
785    /// map.insert_unique(Item { id: "bar".to_string(), value: 2 }).unwrap();
786    /// assert!(map.capacity() >= 100);
787    /// map.shrink_to(10);
788    /// assert!(map.capacity() >= 10);
789    /// map.shrink_to(0);
790    /// assert!(map.capacity() >= 2);
791    /// # }
792    /// ```
793    pub fn shrink_to(&mut self, min_capacity: usize) {
794        // See `shrink_to_fit` for the rationale behind the sequence.
795        let remap = self.items.compact();
796        if !remap.is_identity() {
797            self.tables.key_to_item.remap_indexes(&remap);
798        }
799        self.items.shrink_capacity_to(min_capacity);
800        self.tables.key_to_item.shrink_to(min_capacity);
801    }
802
803    /// Iterates over the items in the map.
804    ///
805    /// Similar to [`HashMap`], the iteration order is arbitrary and not
806    /// guaranteed to be stable.
807    ///
808    /// # Examples
809    ///
810    /// ```
811    /// # #[cfg(feature = "default-hasher")] {
812    /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
813    ///
814    /// #[derive(Debug, PartialEq, Eq, Hash)]
815    /// struct Item {
816    ///     id: String,
817    ///     value: u32,
818    /// }
819    ///
820    /// impl IdHashItem for Item {
821    ///     type Key<'a> = &'a str;
822    ///     fn key(&self) -> Self::Key<'_> {
823    ///         &self.id
824    ///     }
825    ///     id_upcast!();
826    /// }
827    ///
828    /// let mut map = IdHashMap::new();
829    /// map.insert_unique(Item { id: "foo".to_string(), value: 42 }).unwrap();
830    /// map.insert_unique(Item { id: "bar".to_string(), value: 20 }).unwrap();
831    ///
832    /// let mut values: Vec<u32> = map.iter().map(|item| item.value).collect();
833    /// values.sort();
834    /// assert_eq!(values, vec![20, 42]);
835    /// # }
836    /// ```
837    ///
838    /// [`HashMap`]: std::collections::HashMap
839    #[inline]
840    pub fn iter(&self) -> Iter<'_, T> {
841        Iter::new(&self.items)
842    }
843
844    /// Iterates over the items in the map, allowing for mutation.
845    ///
846    /// Similar to [`HashMap`], the iteration order is arbitrary and not
847    /// guaranteed to be stable.
848    ///
849    /// # Examples
850    ///
851    /// ```
852    /// # #[cfg(feature = "default-hasher")] {
853    /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
854    ///
855    /// #[derive(Debug, PartialEq, Eq, Hash)]
856    /// struct Item {
857    ///     id: String,
858    ///     value: u32,
859    /// }
860    ///
861    /// impl IdHashItem for Item {
862    ///     type Key<'a> = &'a str;
863    ///     fn key(&self) -> Self::Key<'_> {
864    ///         &self.id
865    ///     }
866    ///     id_upcast!();
867    /// }
868    ///
869    /// let mut map = IdHashMap::new();
870    /// map.insert_unique(Item { id: "foo".to_string(), value: 42 }).unwrap();
871    /// map.insert_unique(Item { id: "bar".to_string(), value: 20 }).unwrap();
872    ///
873    /// for mut item in map.iter_mut() {
874    ///     item.value *= 2;
875    /// }
876    ///
877    /// assert_eq!(map.get("foo").unwrap().value, 84);
878    /// assert_eq!(map.get("bar").unwrap().value, 40);
879    /// # }
880    /// ```
881    ///
882    /// [`HashMap`]: std::collections::HashMap
883    #[inline]
884    pub fn iter_mut(&mut self) -> IterMut<'_, T, S, A> {
885        IterMut::new(&self.tables, &mut self.items)
886    }
887
888    /// Checks general invariants of the map.
889    ///
890    /// The code below always upholds these invariants, but it's useful to have
891    /// an explicit check for tests.
892    #[doc(hidden)]
893    pub fn validate(
894        &self,
895        compactness: ValidateCompact,
896    ) -> Result<(), ValidationError>
897    where
898        T: fmt::Debug,
899    {
900        self.items.validate(compactness)?;
901        self.tables.validate(self.len(), compactness)?;
902
903        // Check that the indexes are all correct.
904        for (ix, item) in self.items.iter() {
905            let key = item.key();
906            let Some(ix1) = self.find_index(&key) else {
907                return Err(ValidationError::general(format!(
908                    "item at index {ix} has no key1 index"
909                )));
910            };
911
912            if ix1 != ix {
913                return Err(ValidationError::General(format!(
914                    "item at index {ix} has mismatched indexes: ix1: {ix1}",
915                )));
916            }
917        }
918
919        Ok(())
920    }
921
922    /// Inserts a value into the map, removing and returning the conflicting
923    /// item, if any.
924    ///
925    /// # Examples
926    ///
927    /// ```
928    /// # #[cfg(feature = "default-hasher")] {
929    /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
930    ///
931    /// #[derive(Debug, PartialEq, Eq, Hash)]
932    /// struct Item {
933    ///     id: String,
934    ///     value: u32,
935    /// }
936    ///
937    /// impl IdHashItem for Item {
938    ///     type Key<'a> = &'a str;
939    ///     fn key(&self) -> Self::Key<'_> {
940    ///         &self.id
941    ///     }
942    ///     id_upcast!();
943    /// }
944    ///
945    /// let mut map = IdHashMap::new();
946    ///
947    /// // First insertion returns None
948    /// let old = map.insert_overwrite(Item { id: "foo".to_string(), value: 42 });
949    /// assert!(old.is_none());
950    ///
951    /// // Second insertion with same key returns the old value
952    /// let old = map.insert_overwrite(Item { id: "foo".to_string(), value: 100 });
953    /// assert_eq!(old.unwrap().value, 42);
954    /// assert_eq!(map.get("foo").unwrap().value, 100);
955    /// # }
956    /// ```
957    #[doc(alias = "insert")]
958    pub fn insert_overwrite(&mut self, value: T) -> Option<T> {
959        // Go through the entry API so all user code is called before any table
960        // mutation. A panic in user code therefore leaves the map in its
961        // pre-call state.
962        //
963        // We use `vacant.insert_entry` rather than `vacant.insert` to avoid
964        // creating a `RefMut`, which would (unnecessarily) re-hash the key
965        // after the mutation when that `RefMut` is created.
966        match self.entry(value.key()) {
967            Entry::Occupied(mut occupied) => Some(occupied.insert(value)),
968            Entry::Vacant(vacant) => {
969                vacant.insert_entry(value);
970                None
971            }
972        }
973    }
974
975    /// Inserts a value into the set, returning an error if any duplicates were
976    /// added.
977    ///
978    /// # Examples
979    ///
980    /// ```
981    /// # #[cfg(feature = "default-hasher")] {
982    /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
983    ///
984    /// #[derive(Debug, PartialEq, Eq, Hash)]
985    /// struct Item {
986    ///     id: String,
987    ///     value: u32,
988    /// }
989    ///
990    /// impl IdHashItem for Item {
991    ///     type Key<'a> = &'a str;
992    ///     fn key(&self) -> Self::Key<'_> {
993    ///         &self.id
994    ///     }
995    ///     id_upcast!();
996    /// }
997    ///
998    /// let mut map = IdHashMap::new();
999    ///
1000    /// // First insertion succeeds
1001    /// assert!(
1002    ///     map.insert_unique(Item { id: "foo".to_string(), value: 42 }).is_ok()
1003    /// );
1004    ///
1005    /// // Second insertion with different key succeeds
1006    /// assert!(
1007    ///     map.insert_unique(Item { id: "bar".to_string(), value: 20 }).is_ok()
1008    /// );
1009    ///
1010    /// // Third insertion with duplicate key fails
1011    /// assert!(
1012    ///     map.insert_unique(Item { id: "foo".to_string(), value: 100 }).is_err()
1013    /// );
1014    /// # }
1015    /// ```
1016    pub fn insert_unique(
1017        &mut self,
1018        value: T,
1019    ) -> Result<(), DuplicateItem<T, &T>> {
1020        let _ = self.insert_unique_impl(value)?;
1021        Ok(())
1022    }
1023
1024    /// Returns true if the map contains the given key.
1025    ///
1026    /// # Examples
1027    ///
1028    /// ```
1029    /// # #[cfg(feature = "default-hasher")] {
1030    /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
1031    ///
1032    /// #[derive(Debug, PartialEq, Eq, Hash)]
1033    /// struct Item {
1034    ///     id: String,
1035    ///     value: u32,
1036    /// }
1037    ///
1038    /// impl IdHashItem for Item {
1039    ///     type Key<'a> = &'a str;
1040    ///     fn key(&self) -> Self::Key<'_> {
1041    ///         &self.id
1042    ///     }
1043    ///     id_upcast!();
1044    /// }
1045    ///
1046    /// let mut map = IdHashMap::new();
1047    /// map.insert_unique(Item { id: "foo".to_string(), value: 42 }).unwrap();
1048    ///
1049    /// assert!(map.contains_key("foo"));
1050    /// assert!(!map.contains_key("bar"));
1051    /// # }
1052    /// ```
1053    pub fn contains_key<'a, Q>(&'a self, key1: &Q) -> bool
1054    where
1055        Q: ?Sized + Hash + Equivalent<T::Key<'a>>,
1056    {
1057        self.find_index(key1).is_some()
1058    }
1059
1060    /// Gets a reference to the value associated with the given key.
1061    ///
1062    /// # Examples
1063    ///
1064    /// ```
1065    /// # #[cfg(feature = "default-hasher")] {
1066    /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
1067    ///
1068    /// #[derive(Debug, PartialEq, Eq, Hash)]
1069    /// struct Item {
1070    ///     id: String,
1071    ///     value: u32,
1072    /// }
1073    ///
1074    /// impl IdHashItem for Item {
1075    ///     type Key<'a> = &'a str;
1076    ///     fn key(&self) -> Self::Key<'_> {
1077    ///         &self.id
1078    ///     }
1079    ///     id_upcast!();
1080    /// }
1081    ///
1082    /// let mut map = IdHashMap::new();
1083    /// map.insert_unique(Item { id: "foo".to_string(), value: 42 }).unwrap();
1084    ///
1085    /// assert_eq!(map.get("foo").unwrap().value, 42);
1086    /// assert!(map.get("bar").is_none());
1087    /// # }
1088    /// ```
1089    pub fn get<'a, Q>(&'a self, key: &Q) -> Option<&'a T>
1090    where
1091        Q: ?Sized + Hash + Equivalent<T::Key<'a>>,
1092    {
1093        self.find_index(key).map(|ix| &self.items[ix])
1094    }
1095
1096    /// Gets a mutable reference to the value associated with the given key.
1097    ///
1098    /// # Examples
1099    ///
1100    /// ```
1101    /// # #[cfg(feature = "default-hasher")] {
1102    /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
1103    ///
1104    /// #[derive(Debug, PartialEq, Eq, Hash)]
1105    /// struct Item {
1106    ///     id: String,
1107    ///     value: u32,
1108    /// }
1109    ///
1110    /// impl IdHashItem for Item {
1111    ///     type Key<'a> = &'a str;
1112    ///     fn key(&self) -> Self::Key<'_> {
1113    ///         &self.id
1114    ///     }
1115    ///     id_upcast!();
1116    /// }
1117    ///
1118    /// let mut map = IdHashMap::new();
1119    /// map.insert_unique(Item { id: "foo".to_string(), value: 42 }).unwrap();
1120    ///
1121    /// if let Some(mut item) = map.get_mut("foo") {
1122    ///     item.value = 100;
1123    /// }
1124    ///
1125    /// assert_eq!(map.get("foo").unwrap().value, 100);
1126    /// assert!(map.get_mut("bar").is_none());
1127    /// # }
1128    /// ```
1129    pub fn get_mut<'a, Q>(&'a mut self, key: &Q) -> Option<RefMut<'a, T, S>>
1130    where
1131        Q: ?Sized + Hash + Equivalent<T::Key<'a>>,
1132    {
1133        let (dormant_map, index) = {
1134            let (map, dormant_map) = DormantMutRef::new(self);
1135            let index = map.find_index(key)?;
1136            (dormant_map, index)
1137        };
1138
1139        // SAFETY: `map` is not used after this point.
1140        let awakened_map = unsafe { dormant_map.awaken() };
1141        let item = &mut awakened_map.items[index];
1142        let state = awakened_map.tables.state.clone();
1143        let hashes = awakened_map.tables.make_hash(item);
1144        Some(RefMut::new(state, hashes, item))
1145    }
1146
1147    /// Removes an item from the map by its key.
1148    ///
1149    /// # Examples
1150    ///
1151    /// ```
1152    /// # #[cfg(feature = "default-hasher")] {
1153    /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
1154    ///
1155    /// #[derive(Debug, PartialEq, Eq, Hash)]
1156    /// struct Item {
1157    ///     id: String,
1158    ///     value: u32,
1159    /// }
1160    ///
1161    /// impl IdHashItem for Item {
1162    ///     type Key<'a> = &'a str;
1163    ///     fn key(&self) -> Self::Key<'_> {
1164    ///         &self.id
1165    ///     }
1166    ///     id_upcast!();
1167    /// }
1168    ///
1169    /// let mut map = IdHashMap::new();
1170    /// map.insert_unique(Item { id: "foo".to_string(), value: 42 }).unwrap();
1171    ///
1172    /// let removed = map.remove("foo");
1173    /// assert_eq!(removed.unwrap().value, 42);
1174    /// assert!(map.is_empty());
1175    ///
1176    /// // Removing non-existent key returns None
1177    /// assert!(map.remove("bar").is_none());
1178    /// # }
1179    /// ```
1180    pub fn remove<'a, Q>(&'a mut self, key: &Q) -> Option<T>
1181    where
1182        Q: ?Sized + Hash + Equivalent<T::Key<'a>>,
1183    {
1184        let (dormant_map, remove_index) = {
1185            let (map, dormant_map) = DormantMutRef::new(self);
1186            let remove_index = map.find_index(key)?;
1187            (dormant_map, remove_index)
1188        };
1189        // SAFETY: `map` is not used after this point.
1190        let awakened_map = unsafe { dormant_map.awaken() };
1191        awakened_map.remove_by_index(remove_index)
1192    }
1193
1194    /// Retrieves an entry by its key.
1195    ///
1196    /// Due to borrow checker limitations, this always accepts an owned key
1197    /// rather than a borrowed form of it.
1198    ///
1199    /// # Examples
1200    ///
1201    /// ```
1202    /// # #[cfg(feature = "default-hasher")] {
1203    /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
1204    ///
1205    /// #[derive(Debug, PartialEq, Eq, Hash)]
1206    /// struct Item {
1207    ///     id: String,
1208    ///     value: u32,
1209    /// }
1210    ///
1211    /// impl IdHashItem for Item {
1212    ///     type Key<'a> = &'a str;
1213    ///     fn key(&self) -> Self::Key<'_> {
1214    ///         &self.id
1215    ///     }
1216    ///     id_upcast!();
1217    /// }
1218    ///
1219    /// let mut map = IdHashMap::new();
1220    ///
1221    /// // Use entry API for conditional insertion
1222    /// map.entry("foo").or_insert(Item { id: "foo".to_string(), value: 42 });
1223    /// map.entry("bar").or_insert(Item { id: "bar".to_string(), value: 20 });
1224    ///
1225    /// assert_eq!(map.len(), 2);
1226    /// # }
1227    /// ```
1228    pub fn entry<'a>(&'a mut self, key: T::Key<'_>) -> Entry<'a, T, S, A> {
1229        // Why does this always take an owned key? Well, it would seem like we
1230        // should be able to pass in any Q that is equivalent. That results in
1231        // *this* code compiling fine, but callers have trouble using it because
1232        // the borrow checker believes the keys are borrowed for the full 'a
1233        // rather than a shorter lifetime.
1234        //
1235        // By accepting owned keys, we can use the upcast functions to convert
1236        // them to a shorter lifetime (so this function accepts T::Key<'_>
1237        // rather than T::Key<'a>).
1238        //
1239        // Really, the solution here is to allow GATs to require covariant
1240        // parameters. If that were allowed, the borrow checker should be able
1241        // to figure out that keys don't need to be borrowed for the full 'a,
1242        // just for some shorter lifetime.
1243        let (map, dormant_map) = DormantMutRef::new(self);
1244        let key = T::upcast_key(key);
1245        {
1246            // index is explicitly typed to show that it has a trivial Drop impl
1247            // that doesn't capture anything from map.
1248            let index: Option<ItemIndex> = map.tables.key_to_item.find_index(
1249                &map.tables.state,
1250                &key,
1251                |index| map.items[index].key(),
1252            );
1253            if let Some(index) = index {
1254                drop(key);
1255                return Entry::Occupied(
1256                    // SAFETY: `map` is not used after this point.
1257                    unsafe { OccupiedEntry::new(dormant_map, index) },
1258                );
1259            }
1260        }
1261        let hash = map.make_key_hash(&key);
1262        Entry::Vacant(
1263            // SAFETY: `map` is not used after this point.
1264            unsafe { VacantEntry::new(dormant_map, hash) },
1265        )
1266    }
1267
1268    /// Retains only the elements specified by the predicate.
1269    ///
1270    /// In other words, remove all items `T` for which `f(RefMut<T>)` returns
1271    /// false. The elements are visited in an arbitrary order.
1272    ///
1273    /// # Examples
1274    ///
1275    /// ```
1276    /// # #[cfg(feature = "default-hasher")] {
1277    /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
1278    ///
1279    /// #[derive(Debug, PartialEq, Eq, Hash)]
1280    /// struct Item {
1281    ///     id: String,
1282    ///     value: u32,
1283    /// }
1284    ///
1285    /// impl IdHashItem for Item {
1286    ///     type Key<'a> = &'a str;
1287    ///
1288    ///     fn key(&self) -> Self::Key<'_> {
1289    ///         &self.id
1290    ///     }
1291    ///
1292    ///     id_upcast!();
1293    /// }
1294    ///
1295    /// let mut map = IdHashMap::new();
1296    /// map.insert_unique(Item { id: "foo".to_string(), value: 42 }).unwrap();
1297    /// map.insert_unique(Item { id: "bar".to_string(), value: 20 }).unwrap();
1298    /// map.insert_unique(Item { id: "baz".to_string(), value: 99 }).unwrap();
1299    ///
1300    /// // Retain only items where value is greater than 30
1301    /// map.retain(|item| item.value > 30);
1302    ///
1303    /// assert_eq!(map.len(), 2);
1304    /// assert_eq!(map.get("foo").unwrap().value, 42);
1305    /// assert_eq!(map.get("baz").unwrap().value, 99);
1306    /// assert!(map.get("bar").is_none());
1307    /// # }
1308    /// ```
1309    pub fn retain<'a, F>(&'a mut self, mut f: F)
1310    where
1311        F: for<'b> FnMut(RefMut<'b, T, S>) -> bool,
1312    {
1313        let hash_state = self.tables.state.clone();
1314        let (_, mut dormant_items) = DormantMutRef::new(&mut self.items);
1315        let mut removed_item = None;
1316
1317        self.tables.key_to_item.retain(|index| {
1318            // Drop the previously-removed item here, at the top of the next
1319            // iteration.
1320            //
1321            // By now, the prior `key_to_item` entry has been erased, so if
1322            // `drop` below panics, `key_to_item` and `items` remain in sync.
1323            // Dropping the item at the end of the prior iteration would
1324            // unwind before the table erased the entry, leaving `key_to_item`
1325            // pointing at a slot we already removed from `items`.
1326            drop(removed_item.take());
1327
1328            let (item, dormant_items) = {
1329                // SAFETY: All uses of `items` ended in the previous iteration.
1330                let items = unsafe { dormant_items.reborrow() };
1331                let (items, dormant_items) = DormantMutRef::new(items);
1332                let item: &'a mut T = items
1333                    .get_mut(index)
1334                    .expect("all indexes are present in self.items");
1335                (item, dormant_items)
1336            };
1337
1338            let (hash, dormant_item) = {
1339                let (item, dormant_item): (&'a mut T, _) =
1340                    DormantMutRef::new(item);
1341                // Use T::key(item) rather than item.key() to force the key
1342                // trait function to be called for T rather than &mut T.
1343                let key = T::key(item);
1344                let hash = hash_state.hash_one(key);
1345                (MapHash::new(hash), dormant_item)
1346            };
1347
1348            let retain = {
1349                // SAFETY: The original item is no longer used after the second
1350                // block above. dormant_items, from which item is derived, is
1351                // currently dormant.
1352                let item = unsafe { dormant_item.awaken() };
1353
1354                let ref_mut = RefMut::new(hash_state.clone(), hash, item);
1355                f(ref_mut)
1356            };
1357
1358            if retain {
1359                true
1360            } else {
1361                // SAFETY: The original items is no longer used after the first
1362                // block above, and item + dormant item have been used above.
1363                let items = unsafe { dormant_items.awaken() };
1364                removed_item = Some(
1365                    items
1366                        .remove(index)
1367                        .expect("all indexes are present in self.items"),
1368                );
1369                false
1370            }
1371        });
1372
1373        // Anything in `removed_item` is implicitly dropped now.
1374    }
1375
1376    fn find_index<'a, Q>(&'a self, k: &Q) -> Option<ItemIndex>
1377    where
1378        Q: Hash + Equivalent<T::Key<'a>> + ?Sized,
1379    {
1380        self.tables
1381            .key_to_item
1382            .find_index(&self.tables.state, k, |index| self.items[index].key())
1383    }
1384
1385    fn make_hash(&self, item: &T) -> MapHash {
1386        self.tables.make_hash(item)
1387    }
1388
1389    fn make_key_hash(&self, key: &T::Key<'_>) -> MapHash {
1390        self.tables.make_key_hash::<T>(key)
1391    }
1392
1393    pub(super) fn get_by_index(&self, index: ItemIndex) -> Option<&T> {
1394        self.items.get(index)
1395    }
1396
1397    pub(super) fn get_by_index_mut(
1398        &mut self,
1399        index: ItemIndex,
1400    ) -> Option<RefMut<'_, T, S>> {
1401        let state = self.tables.state.clone();
1402        let hashes = self.make_hash(&self.items[index]);
1403        let item = &mut self.items[index];
1404        Some(RefMut::new(state, hashes, item))
1405    }
1406
1407    pub(super) fn insert_unique_impl(
1408        &mut self,
1409        value: T,
1410    ) -> Result<ItemIndex, DuplicateItem<T, &T>> {
1411        let mut duplicates = BTreeSet::new();
1412
1413        // Check for duplicates *before* inserting the new item, because we
1414        // don't want to partially insert the new item and then have to roll
1415        // back.
1416        let key = value.key();
1417        let state = &self.tables.state;
1418
1419        let entry = match self
1420            .tables
1421            .key_to_item
1422            .entry(state, key, |index| self.items[index].key())
1423        {
1424            hash_table::Entry::Occupied(slot) => {
1425                duplicates.insert(slot.get());
1426                None
1427            }
1428            hash_table::Entry::Vacant(slot) => Some(slot),
1429        };
1430
1431        if !duplicates.is_empty() {
1432            return Err(DuplicateItem::__internal_new(
1433                value,
1434                duplicates.iter().map(|ix| &self.items[*ix]).collect(),
1435            ));
1436        }
1437
1438        let next_index = self.items.assert_can_grow().insert(value);
1439        entry.unwrap().insert(next_index);
1440
1441        Ok(next_index)
1442    }
1443
1444    pub(super) fn remove_by_index(
1445        &mut self,
1446        remove_index: ItemIndex,
1447    ) -> Option<T> {
1448        // For panic safety, compute the key hash and look up the table entry
1449        // while `self.items` still holds the value, then remove from the table
1450        // and items in sequence. This lookup deliberately matches by
1451        // `ItemIndex` rather than by user `Eq`: at this point we already know
1452        // which item is being removed, and user `Eq` might be pathological.
1453        //
1454        // hashbrown's `find_entry_by_hash` is panic-safe because the table is
1455        // not mutated until `OccupiedEntry::remove` is called, so a panic while
1456        // hashing leaves both items and the table unmodified. (Unlike the
1457        // IdOrdMap path, we don't need a separate two-phase commit: the
1458        // BTreeMap analog has to guard against a user-`Ord` panic during the
1459        // tree walk, but the hash walk here never invokes user code.)
1460        //
1461        // If the hash lookup misses, which can happen when `mem::forget` is
1462        // called on a `RefMut` after the ID was changed, the item's current key
1463        // now hashes to a different bucket than the one its entry sits in. In
1464        // that case, we fall back to a linear scan by `ItemIndex`. This keeps
1465        // the table and item set consistent with each other across silent key
1466        // mutations, mirroring `MapBTreeTable::remove_exact`.
1467        //
1468        // This is not expected to be the common case (why are you calling
1469        // mem::forget on a RefMut?), but guarding against it explicitly makes
1470        // our invariants easier to reason about.
1471        let item = self.items.get(remove_index)?;
1472        let state = &self.tables.state;
1473        let hash = state.hash_one(item.key());
1474        match self
1475            .tables
1476            .key_to_item
1477            .find_entry_by_hash(hash, |index| index == remove_index)
1478        {
1479            Ok(entry) => entry.remove(),
1480            Err(()) => self.tables.key_to_item.remove_by_index(remove_index),
1481        }
1482        Some(
1483            self.items
1484                .remove(remove_index)
1485                .expect("items[remove_index] was Occupied above"),
1486        )
1487    }
1488
1489    pub(super) fn replace_at_index(&mut self, index: ItemIndex, value: T) -> T {
1490        // We check the key before removing it, to avoid leaving the map in an
1491        // inconsistent state.
1492        let old_key =
1493            self.get_by_index(index).expect("index is known to be valid").key();
1494        if T::upcast_key(old_key) != value.key() {
1495            panic!(
1496                "must insert a value with \
1497                 the same key used to create the entry"
1498            );
1499        }
1500
1501        // Now that we know the key is the same, we can replace the value
1502        // directly without needing to tweak any tables.
1503        self.items.replace(index, value)
1504    }
1505}
1506
1507impl<'a, T, S: Clone + BuildHasher, A: Allocator> fmt::Debug
1508    for IdHashMap<T, S, A>
1509where
1510    T: IdHashItem + fmt::Debug,
1511    T::Key<'a>: fmt::Debug,
1512    T: 'a,
1513{
1514    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1515        let mut map = f.debug_map();
1516
1517        for item in self.iter() {
1518            let key = item.key();
1519
1520            // SAFETY:
1521            //
1522            // * Lifetime extension: for a type T and two lifetime params 'a and
1523            //   'b, T<'a> and T<'b> aren't guaranteed to have the same layout,
1524            //   but (a) that is true today and (b) it would be shocking and
1525            //   break half the Rust ecosystem if that were to change in the
1526            //   future.
1527            // * We only use key within the scope of this block before immediately
1528            //   dropping it. In particular, map.entry calls key.fmt() without
1529            //   holding a reference to it.
1530            let key: T::Key<'a> =
1531                unsafe { core::mem::transmute::<T::Key<'_>, T::Key<'a>>(key) };
1532
1533            map.entry(&key, item);
1534        }
1535        map.finish()
1536    }
1537}
1538
1539impl<T: IdHashItem + PartialEq, S: Clone + BuildHasher, A: Allocator> PartialEq
1540    for IdHashMap<T, S, A>
1541{
1542    fn eq(&self, other: &Self) -> bool {
1543        // Implementing PartialEq for IdHashMap is tricky because IdHashMap is
1544        // not semantically like an IndexMap: two maps are equivalent even if
1545        // their items are in a different order. In other words, any permutation
1546        // of items is equivalent.
1547        //
1548        // We also can't sort the items because they're not necessarily Ord.
1549        //
1550        // So we write a custom equality check that checks that each key in one
1551        // map points to the same item as in the other map.
1552
1553        if self.items.len() != other.items.len() {
1554            return false;
1555        }
1556
1557        // Walk over all the items in the first map and check that they point to
1558        // the same item in the second map.
1559        for item in self.items.values() {
1560            let k1 = item.key();
1561
1562            // Check that the indexes are the same in the other map.
1563            let Some(other_ix) = other.find_index(&k1) else {
1564                return false;
1565            };
1566
1567            // Check that the other map's item is the same as this map's
1568            // item. (This is what we use the `PartialEq` bound on T for.)
1569            //
1570            // Because we've checked that other_ix is Some, we know that it is
1571            // valid and points to the expected item.
1572            let other_item = &other.items[other_ix];
1573            if item != other_item {
1574                return false;
1575            }
1576        }
1577
1578        true
1579    }
1580}
1581
1582// The Eq bound on T ensures that the TriHashMap forms an equivalence class.
1583impl<T: IdHashItem + Eq, S: Clone + BuildHasher, A: Allocator> Eq
1584    for IdHashMap<T, S, A>
1585{
1586}
1587
1588/// The `Extend` implementation overwrites duplicates. In the future, there will
1589/// also be an `extend_unique` method that will return an error.
1590///
1591/// # Examples
1592///
1593/// ```
1594/// # #[cfg(feature = "default-hasher")] {
1595/// use iddqd::{IdHashItem, IdHashMap, id_upcast};
1596///
1597/// #[derive(Debug, PartialEq, Eq, Hash)]
1598/// struct Item {
1599///     id: String,
1600///     value: u32,
1601/// }
1602///
1603/// impl IdHashItem for Item {
1604///     type Key<'a> = &'a str;
1605///     fn key(&self) -> Self::Key<'_> {
1606///         &self.id
1607///     }
1608///     id_upcast!();
1609/// }
1610///
1611/// let mut map = IdHashMap::new();
1612/// map.insert_unique(Item { id: "foo".to_string(), value: 42 }).unwrap();
1613///
1614/// let new_items = vec![
1615///     Item { id: "foo".to_string(), value: 100 }, // overwrites existing
1616///     Item { id: "bar".to_string(), value: 20 },  // new item
1617/// ];
1618///
1619/// map.extend(new_items);
1620/// assert_eq!(map.len(), 2);
1621/// assert_eq!(map.get("foo").unwrap().value, 100); // overwritten
1622/// assert_eq!(map.get("bar").unwrap().value, 20); // new
1623///
1624/// # }
1625/// ```
1626impl<T: IdHashItem, S: Clone + BuildHasher, A: Allocator> Extend<T>
1627    for IdHashMap<T, S, A>
1628{
1629    fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
1630        // Keys may already be present in the map, or multiple times in the
1631        // iterator. Reserve the entire hint lower bound if the map is empty.
1632        // Otherwise reserve half the hint (rounded up), so the map will only
1633        // resize twice in the worst case.
1634        let iter = iter.into_iter();
1635        let reserve = if self.is_empty() {
1636            iter.size_hint().0
1637        } else {
1638            iter.size_hint().0.div_ceil(2)
1639        };
1640        self.reserve(reserve);
1641        for item in iter {
1642            self.insert_overwrite(item);
1643        }
1644    }
1645}
1646
1647impl<'a, T: IdHashItem, S: Clone + BuildHasher, A: Allocator> IntoIterator
1648    for &'a IdHashMap<T, S, A>
1649{
1650    type Item = &'a T;
1651    type IntoIter = Iter<'a, T>;
1652
1653    /// Creates an iterator over references to the items in the map.
1654    ///
1655    /// # Examples
1656    ///
1657    /// ```
1658    /// # #[cfg(feature = "default-hasher")] {
1659    /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
1660    ///
1661    /// #[derive(Debug, PartialEq, Eq, Hash)]
1662    /// struct Item {
1663    ///     id: String,
1664    ///     value: u32,
1665    /// }
1666    ///
1667    /// impl IdHashItem for Item {
1668    ///     type Key<'a> = &'a str;
1669    ///     fn key(&self) -> Self::Key<'_> {
1670    ///         &self.id
1671    ///     }
1672    ///     id_upcast!();
1673    /// }
1674    ///
1675    /// let mut map = IdHashMap::new();
1676    /// map.insert_unique(Item { id: "foo".to_string(), value: 42 }).unwrap();
1677    /// map.insert_unique(Item { id: "bar".to_string(), value: 20 }).unwrap();
1678    ///
1679    /// let mut values: Vec<u32> =
1680    ///     (&map).into_iter().map(|item| item.value).collect();
1681    /// values.sort();
1682    /// assert_eq!(values, vec![20, 42]);
1683    /// # }
1684    /// ```
1685    #[inline]
1686    fn into_iter(self) -> Self::IntoIter {
1687        self.iter()
1688    }
1689}
1690
1691impl<'a, T: IdHashItem, S: Clone + BuildHasher, A: Allocator> IntoIterator
1692    for &'a mut IdHashMap<T, S, A>
1693{
1694    type Item = RefMut<'a, T, S>;
1695    type IntoIter = IterMut<'a, T, S, A>;
1696
1697    /// Creates an iterator over mutable references to the items in the map.
1698    ///
1699    /// # Examples
1700    ///
1701    /// ```
1702    /// # #[cfg(feature = "default-hasher")] {
1703    /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
1704    ///
1705    /// #[derive(Debug, PartialEq, Eq, Hash)]
1706    /// struct Item {
1707    ///     id: String,
1708    ///     value: u32,
1709    /// }
1710    ///
1711    /// impl IdHashItem for Item {
1712    ///     type Key<'a> = &'a str;
1713    ///     fn key(&self) -> Self::Key<'_> {
1714    ///         &self.id
1715    ///     }
1716    ///     id_upcast!();
1717    /// }
1718    ///
1719    /// let mut map = IdHashMap::new();
1720    /// map.insert_unique(Item { id: "foo".to_string(), value: 42 }).unwrap();
1721    /// map.insert_unique(Item { id: "bar".to_string(), value: 20 }).unwrap();
1722    ///
1723    /// for mut item in &mut map {
1724    ///     item.value *= 2;
1725    /// }
1726    ///
1727    /// assert_eq!(map.get("foo").unwrap().value, 84);
1728    /// assert_eq!(map.get("bar").unwrap().value, 40);
1729    /// # }
1730    /// ```
1731    #[inline]
1732    fn into_iter(self) -> Self::IntoIter {
1733        self.iter_mut()
1734    }
1735}
1736
1737impl<T: IdHashItem, S: Clone + BuildHasher, A: Allocator> IntoIterator
1738    for IdHashMap<T, S, A>
1739{
1740    type Item = T;
1741    type IntoIter = IntoIter<T, A>;
1742
1743    /// Consumes the map and creates an iterator over the owned items.
1744    ///
1745    /// # Examples
1746    ///
1747    /// ```
1748    /// # #[cfg(feature = "default-hasher")] {
1749    /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
1750    ///
1751    /// #[derive(Debug, PartialEq, Eq, Hash)]
1752    /// struct Item {
1753    ///     id: String,
1754    ///     value: u32,
1755    /// }
1756    ///
1757    /// impl IdHashItem for Item {
1758    ///     type Key<'a> = &'a str;
1759    ///     fn key(&self) -> Self::Key<'_> {
1760    ///         &self.id
1761    ///     }
1762    ///     id_upcast!();
1763    /// }
1764    ///
1765    /// let mut map = IdHashMap::new();
1766    /// map.insert_unique(Item { id: "foo".to_string(), value: 42 }).unwrap();
1767    /// map.insert_unique(Item { id: "bar".to_string(), value: 20 }).unwrap();
1768    ///
1769    /// let mut values: Vec<u32> = map.into_iter().map(|item| item.value).collect();
1770    /// values.sort();
1771    /// assert_eq!(values, vec![20, 42]);
1772    /// # }
1773    /// ```
1774    #[inline]
1775    fn into_iter(self) -> Self::IntoIter {
1776        IntoIter::new(self.items)
1777    }
1778}
1779
1780/// The `FromIterator` implementation for `IdHashMap` overwrites duplicate
1781/// items.
1782///
1783/// # Examples
1784///
1785/// ```
1786/// # #[cfg(feature = "default-hasher")] {
1787/// use iddqd::{IdHashItem, IdHashMap, id_upcast};
1788///
1789/// #[derive(Debug, PartialEq, Eq, Hash)]
1790/// struct Item {
1791///     id: String,
1792///     value: u32,
1793/// }
1794///
1795/// impl IdHashItem for Item {
1796///     type Key<'a> = &'a str;
1797///     fn key(&self) -> Self::Key<'_> {
1798///         &self.id
1799///     }
1800///     id_upcast!();
1801/// }
1802///
1803/// let items = vec![
1804///     Item { id: "foo".to_string(), value: 42 },
1805///     Item { id: "bar".to_string(), value: 20 },
1806///     Item { id: "foo".to_string(), value: 100 }, // duplicate key, overwrites
1807/// ];
1808///
1809/// let map: IdHashMap<Item> = items.into_iter().collect();
1810/// assert_eq!(map.len(), 2);
1811/// assert_eq!(map.get("foo").unwrap().value, 100); // last value wins
1812/// assert_eq!(map.get("bar").unwrap().value, 20);
1813/// # }
1814/// ```
1815impl<T: IdHashItem, S: Default + Clone + BuildHasher, A: Allocator + Default>
1816    FromIterator<T> for IdHashMap<T, S, A>
1817{
1818    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
1819        let mut map = IdHashMap::default();
1820        map.extend(iter);
1821        map
1822    }
1823}
1824
1825#[cfg(all(test, feature = "std"))]
1826mod tests {
1827    use super::*;
1828    use core::{cell::Cell, hash::Hasher};
1829
1830    std::thread_local! {
1831        static USER_HASH_CALLS: Cell<u32> = const { Cell::new(0) };
1832    }
1833
1834    #[derive(Debug)]
1835    struct CountedKey(u32);
1836
1837    impl Hash for CountedKey {
1838        fn hash<H: Hasher>(&self, state: &mut H) {
1839            USER_HASH_CALLS.with(|c| c.set(c.get() + 1));
1840            self.0.hash(state);
1841        }
1842    }
1843
1844    impl PartialEq for CountedKey {
1845        fn eq(&self, other: &Self) -> bool {
1846            self.0 == other.0
1847        }
1848    }
1849    impl Eq for CountedKey {}
1850
1851    #[derive(Debug)]
1852    struct CountedItem {
1853        id: u32,
1854    }
1855
1856    impl IdHashItem for CountedItem {
1857        type Key<'a> = CountedKey;
1858        fn key(&self) -> Self::Key<'_> {
1859            CountedKey(self.id)
1860        }
1861        id_upcast!();
1862    }
1863
1864    // This is a unit test and not an integration test to ensure rehashing
1865    // actually happens. (Rehashing is not externally observable in integration
1866    // tests.)
1867    #[test]
1868    fn reserve_rehash_uses_cached_hash() {
1869        let mut map = IdHashMap::<CountedItem, _>::with_hasher(
1870            foldhash::fast::FixedState::with_seed(0),
1871        );
1872        // Insert items (legitimately calls user Hash).
1873        for id in [
1874            0u32, 17, 1, 12, 5, 21, 8, 10, 18, 4, 16, 22, 9, 24, 23, 13, 7, 25,
1875            26, 20, 31, 11, 14, 2, 6,
1876        ] {
1877            let _ = map.insert_overwrite(CountedItem { id });
1878        }
1879        // Drop most entries, leaving the table heavy with tombstones so the
1880        // next reserve favors `rehash_in_place` over a fresh-allocation grow.
1881        map.retain(|item| item.id % 2 == 1 && item.id % 3 != 0);
1882
1883        USER_HASH_CALLS.with(|c| c.set(0));
1884        let rehash_calls = map.tables.key_to_item.reserve_counting_rehash(10);
1885        let user_calls = USER_HASH_CALLS.with(Cell::get);
1886
1887        assert!(
1888            rehash_calls > 0,
1889            "expected reserve to invoke the rehash callback at least once \
1890             (setup did not actually trigger a rehash; if hashbrown's \
1891             growth/rehash heuristic changed, retune the constants)",
1892        );
1893        assert_eq!(
1894            user_calls, 0,
1895            "reserve must not invoke user `Hash` during rehash; got \
1896             {user_calls} call(s) for {rehash_calls} rehash-callback \
1897             invocation(s)",
1898        );
1899
1900        map.validate(ValidateCompact::NonCompact)
1901            .expect("map remains valid after reserve");
1902    }
1903}