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