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