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