Skip to main content

iddqd/id_hash_map/
imp.rs

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