Skip to main content

iddqd/bi_hash_map/
imp.rs

1use super::{
2    Entry, IntoIter, Iter, IterMut, OccupiedEntry, RefMut, VacantEntry,
3    entry::OccupiedEntryRef,
4    entry_indexes::{DisjointKeys, EntryIndexes},
5    tables::BiHashMapTables,
6};
7use crate::{
8    BiHashItem, DefaultHashBuilder,
9    bi_hash_map::entry::OccupiedEntryMut,
10    errors::{DuplicateItem, TryReserveError},
11    internal::{ValidateCompact, ValidationError},
12    support::{
13        ItemIndex,
14        alloc::{Allocator, Global, global_alloc},
15        borrow::DormantMutRef,
16        fmt_utils::StrDisplayAsDebug,
17        hash_table,
18        item_set::ItemSet,
19        map_hash::MapHash,
20    },
21};
22use alloc::{collections::BTreeSet, vec::Vec};
23use core::{
24    fmt,
25    hash::{BuildHasher, Hash},
26};
27use equivalent::Equivalent;
28
29#[derive(Debug)]
30#[must_use]
31struct PreparedDuplicate {
32    index: ItemIndex,
33    hashes: [MapHash; 2],
34}
35
36impl PreparedDuplicate {
37    fn from_indexes<const N: usize>(
38        indexes: [Option<ItemIndex>; N],
39        mut prepare: impl FnMut(ItemIndex) -> Self,
40    ) -> Vec<Self> {
41        let mut duplicates = Vec::new();
42
43        for index in indexes.into_iter().flatten() {
44            if duplicates
45                .iter()
46                .any(|duplicate: &PreparedDuplicate| duplicate.index == index)
47            {
48                continue;
49            }
50
51            duplicates.push(prepare(index));
52        }
53
54        duplicates
55    }
56}
57
58#[derive(Debug)]
59#[must_use]
60struct PreparedInsertOverwrite {
61    index1: Option<ItemIndex>,
62    index2: Option<ItemIndex>,
63    duplicates: Vec<PreparedDuplicate>,
64    hashes: [MapHash; 2],
65}
66
67impl PreparedInsertOverwrite {
68    #[inline]
69    fn duplicate_count(&self) -> usize {
70        self.duplicates.len()
71    }
72
73    // ItemSet only needs to grow when no duplicate slot will be freed during
74    // commit. Hash-table insertion capacity is reserved separately.
75    #[inline]
76    fn needs_new_item_slot(&self) -> bool {
77        self.duplicates.is_empty()
78    }
79}
80
81/// A 1:1 (bijective) map for two keys and a value.
82///
83/// The storage mechanism is a fast hash table of integer indexes to items, with
84/// these indexes stored in two hash tables. This allows for efficient lookups
85/// by either of the two keys and prevents duplicates.
86///
87/// # Examples
88///
89/// ```
90/// # #[cfg(feature = "default-hasher")] {
91/// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
92///
93/// // Define a struct with two keys and a value.
94/// #[derive(Debug, PartialEq, Eq)]
95/// struct MyItem {
96///     id: u32,
97///     name: &'static str,
98///     value: i32,
99/// }
100///
101/// // Implement BiHashItem for the struct.
102/// impl BiHashItem for MyItem {
103///     type K1<'a> = u32;
104///     type K2<'a> = &'a str;
105///
106///     fn key1(&self) -> Self::K1<'_> {
107///         self.id
108///     }
109///     fn key2(&self) -> Self::K2<'_> {
110///         self.name
111///     }
112///
113///     bi_upcast!();
114/// }
115///
116/// // Create a new BiHashMap and insert items.
117/// let mut map = BiHashMap::new();
118/// map.insert_unique(MyItem { id: 1, name: "foo", value: 42 }).unwrap();
119/// map.insert_unique(MyItem { id: 2, name: "bar", value: 99 }).unwrap();
120///
121/// // Look up by the first key.
122/// assert_eq!(map.get1(&1).unwrap().value, 42);
123/// assert_eq!(map.get1(&2).unwrap().value, 99);
124/// assert!(map.get1(&3).is_none());
125///
126/// // Look up by the second key.
127/// assert_eq!(map.get2(&"foo").unwrap().value, 42);
128/// assert_eq!(map.get2(&"bar").unwrap().value, 99);
129/// assert!(map.get2(&"baz").is_none());
130/// # }
131/// ```
132#[derive(Clone)]
133pub struct BiHashMap<T, S = DefaultHashBuilder, A: Allocator = Global> {
134    pub(super) items: ItemSet<T, A>,
135    // Invariant: the values (ItemIndex) in these tables are valid indexes into
136    // `items`, and are a 1:1 mapping.
137    pub(super) tables: BiHashMapTables<S, A>,
138}
139
140impl<T: BiHashItem, S: Default, A: Allocator + Default> Default
141    for BiHashMap<T, S, A>
142{
143    fn default() -> Self {
144        Self {
145            items: ItemSet::with_capacity_in(0, A::default()),
146            tables: BiHashMapTables::default(),
147        }
148    }
149}
150
151#[cfg(feature = "default-hasher")]
152impl<T: BiHashItem> BiHashMap<T> {
153    /// Creates a new, empty `BiHashMap`.
154    ///
155    /// # Examples
156    ///
157    /// ```
158    /// # #[cfg(feature = "default-hasher")] {
159    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
160    ///
161    /// #[derive(Debug, PartialEq, Eq)]
162    /// struct Item {
163    ///     id: u32,
164    ///     name: String,
165    ///     value: i32,
166    /// }
167    ///
168    /// impl BiHashItem for Item {
169    ///     type K1<'a> = u32;
170    ///     type K2<'a> = &'a str;
171    ///
172    ///     fn key1(&self) -> Self::K1<'_> {
173    ///         self.id
174    ///     }
175    ///     fn key2(&self) -> Self::K2<'_> {
176    ///         &self.name
177    ///     }
178    ///     bi_upcast!();
179    /// }
180    ///
181    /// let map: BiHashMap<Item> = BiHashMap::new();
182    /// assert!(map.is_empty());
183    /// assert_eq!(map.len(), 0);
184    /// # }
185    /// ```
186    #[inline]
187    pub fn new() -> Self {
188        Self { items: ItemSet::new(), tables: BiHashMapTables::default() }
189    }
190
191    /// Creates a new `BiHashMap` with the given capacity.
192    ///
193    /// # Examples
194    ///
195    /// ```
196    /// # #[cfg(feature = "default-hasher")] {
197    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
198    ///
199    /// #[derive(Debug, PartialEq, Eq)]
200    /// struct Item {
201    ///     id: u32,
202    ///     name: String,
203    ///     value: i32,
204    /// }
205    ///
206    /// impl BiHashItem for Item {
207    ///     type K1<'a> = u32;
208    ///     type K2<'a> = &'a str;
209    ///
210    ///     fn key1(&self) -> Self::K1<'_> {
211    ///         self.id
212    ///     }
213    ///     fn key2(&self) -> Self::K2<'_> {
214    ///         &self.name
215    ///     }
216    ///     bi_upcast!();
217    /// }
218    ///
219    /// let map: BiHashMap<Item> = BiHashMap::with_capacity(10);
220    /// assert!(map.capacity() >= 10);
221    /// assert!(map.is_empty());
222    /// # }
223    /// ```
224    pub fn with_capacity(capacity: usize) -> Self {
225        Self {
226            items: ItemSet::with_capacity_in(capacity, global_alloc()),
227            tables: BiHashMapTables::with_capacity_and_hasher_in(
228                capacity,
229                DefaultHashBuilder::default(),
230                global_alloc(),
231            ),
232        }
233    }
234}
235
236impl<T: BiHashItem, S: BuildHasher> BiHashMap<T, S> {
237    /// Creates a new `BiHashMap` with the given hasher.
238    ///
239    /// # Examples
240    ///
241    /// ```
242    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
243    /// use std::collections::hash_map::RandomState;
244    ///
245    /// #[derive(Debug, PartialEq, Eq)]
246    /// struct Item {
247    ///     id: u32,
248    ///     name: String,
249    ///     value: i32,
250    /// }
251    ///
252    /// impl BiHashItem for Item {
253    ///     type K1<'a> = u32;
254    ///     type K2<'a> = &'a str;
255    ///
256    ///     fn key1(&self) -> Self::K1<'_> {
257    ///         self.id
258    ///     }
259    ///     fn key2(&self) -> Self::K2<'_> {
260    ///         &self.name
261    ///     }
262    ///     bi_upcast!();
263    /// }
264    ///
265    /// let hasher = RandomState::new();
266    /// let map: BiHashMap<Item, RandomState> = BiHashMap::with_hasher(hasher);
267    /// assert!(map.is_empty());
268    /// ```
269    pub const fn with_hasher(hasher: S) -> Self {
270        Self {
271            items: ItemSet::new(),
272            tables: BiHashMapTables::with_hasher(hasher),
273        }
274    }
275
276    /// Creates a new `BiHashMap` with the given capacity and hasher.
277    ///
278    /// # Examples
279    ///
280    /// ```
281    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
282    /// use std::collections::hash_map::RandomState;
283    ///
284    /// #[derive(Debug, PartialEq, Eq)]
285    /// struct Item {
286    ///     id: u32,
287    ///     name: String,
288    ///     value: i32,
289    /// }
290    ///
291    /// impl BiHashItem for Item {
292    ///     type K1<'a> = u32;
293    ///     type K2<'a> = &'a str;
294    ///
295    ///     fn key1(&self) -> Self::K1<'_> {
296    ///         self.id
297    ///     }
298    ///     fn key2(&self) -> Self::K2<'_> {
299    ///         &self.name
300    ///     }
301    ///     bi_upcast!();
302    /// }
303    ///
304    /// let hasher = RandomState::new();
305    /// let map: BiHashMap<Item, _> =
306    ///     BiHashMap::with_capacity_and_hasher(10, hasher);
307    /// assert!(map.capacity() >= 10);
308    /// assert!(map.is_empty());
309    /// ```
310    pub fn with_capacity_and_hasher(capacity: usize, hasher: S) -> Self {
311        Self {
312            items: ItemSet::with_capacity_in(capacity, global_alloc()),
313            tables: BiHashMapTables::with_capacity_and_hasher_in(
314                capacity,
315                hasher,
316                global_alloc(),
317            ),
318        }
319    }
320}
321
322#[cfg(feature = "default-hasher")]
323impl<T: BiHashItem, A: Clone + Allocator> BiHashMap<T, DefaultHashBuilder, A> {
324    /// Creates a new empty `BiHashMap` using the given allocator.
325    ///
326    /// Requires the `allocator-api2` feature to be enabled.
327    ///
328    /// # Examples
329    ///
330    /// Using the [`bumpalo`](https://docs.rs/bumpalo) allocator:
331    ///
332    /// ```
333    /// # #[cfg(all(feature = "default-hasher", feature = "allocator-api2"))] {
334    /// use iddqd::{BiHashMap, BiHashItem, bi_upcast};
335    /// # use iddqd_test_utils::bumpalo;
336    ///
337    /// #[derive(Debug, PartialEq, Eq)]
338    /// struct Item {
339    ///     id: u32,
340    ///     name: String,
341    ///     value: i32,
342    /// }
343    ///
344    /// impl BiHashItem for Item {
345    ///     type K1<'a> = u32;
346    ///     type K2<'a> = &'a str;
347    ///
348    ///     fn key1(&self) -> Self::K1<'_> {
349    ///         self.id
350    ///     }
351    ///     fn key2(&self) -> Self::K2<'_> {
352    ///         &self.name
353    ///     }
354    ///     bi_upcast!();
355    /// }
356    ///
357    /// // Define a new allocator.
358    /// let bump = bumpalo::Bump::new();
359    /// // Create a new BiHashMap using the allocator.
360    /// let map: BiHashMap<Item, _, &bumpalo::Bump> = BiHashMap::new_in(&bump);
361    /// assert!(map.is_empty());
362    /// # }
363    /// ```
364    pub fn new_in(alloc: A) -> Self {
365        Self {
366            items: ItemSet::with_capacity_in(0, alloc.clone()),
367            tables: BiHashMapTables::with_capacity_and_hasher_in(
368                0,
369                DefaultHashBuilder::default(),
370                alloc,
371            ),
372        }
373    }
374
375    /// Creates an empty `BiHashMap` with the specified capacity using the given
376    /// allocator.
377    ///
378    /// Requires the `allocator-api2` feature to be enabled.
379    ///
380    /// # Examples
381    ///
382    /// Using the [`bumpalo`](https://docs.rs/bumpalo) allocator:
383    ///
384    /// ```
385    /// # #[cfg(all(feature = "default-hasher", feature = "allocator-api2"))] {
386    /// use iddqd::{BiHashMap, BiHashItem, bi_upcast};
387    /// # use iddqd_test_utils::bumpalo;
388    ///
389    /// #[derive(Debug, PartialEq, Eq)]
390    /// struct Item {
391    ///     id: u32,
392    ///     name: String,
393    ///     value: i32,
394    /// }
395    ///
396    /// impl BiHashItem for Item {
397    ///     type K1<'a> = u32;
398    ///     type K2<'a> = &'a str;
399    ///
400    ///     fn key1(&self) -> Self::K1<'_> {
401    ///         self.id
402    ///     }
403    ///     fn key2(&self) -> Self::K2<'_> {
404    ///         &self.name
405    ///     }
406    ///     bi_upcast!();
407    /// }
408    ///
409    /// // Define a new allocator.
410    /// let bump = bumpalo::Bump::new();
411    /// // Create a new BiHashMap with capacity using the allocator.
412    /// let map: BiHashMap<Item, _, &bumpalo::Bump> = BiHashMap::with_capacity_in(10, &bump);
413    /// assert!(map.capacity() >= 10);
414    /// assert!(map.is_empty());
415    /// # }
416    /// ```
417    pub fn with_capacity_in(capacity: usize, alloc: A) -> Self {
418        Self {
419            items: ItemSet::with_capacity_in(capacity, alloc.clone()),
420            tables: BiHashMapTables::with_capacity_and_hasher_in(
421                capacity,
422                DefaultHashBuilder::default(),
423                alloc,
424            ),
425        }
426    }
427}
428
429impl<T: BiHashItem, S: Clone + BuildHasher, A: Clone + Allocator>
430    BiHashMap<T, S, A>
431{
432    /// Creates a new, empty `BiHashMap` with the given hasher and allocator.
433    ///
434    /// Requires the `allocator-api2` feature to be enabled.
435    ///
436    /// # Examples
437    ///
438    /// Using the [`bumpalo`](https://docs.rs/bumpalo) allocator:
439    ///
440    /// ```
441    /// # #[cfg(feature = "allocator-api2")] {
442    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
443    /// use std::collections::hash_map::RandomState;
444    /// # use iddqd_test_utils::bumpalo;
445    ///
446    /// #[derive(Debug, PartialEq, Eq)]
447    /// struct Item {
448    ///     id: u32,
449    ///     name: String,
450    ///     value: i32,
451    /// }
452    ///
453    /// impl BiHashItem for Item {
454    ///     type K1<'a> = u32;
455    ///     type K2<'a> = &'a str;
456    ///
457    ///     fn key1(&self) -> Self::K1<'_> {
458    ///         self.id
459    ///     }
460    ///     fn key2(&self) -> Self::K2<'_> {
461    ///         &self.name
462    ///     }
463    ///     bi_upcast!();
464    /// }
465    ///
466    /// // Define a new allocator.
467    /// let bump = bumpalo::Bump::new();
468    /// let hasher = RandomState::new();
469    /// // Create a new BiHashMap with hasher using the allocator.
470    /// let map: BiHashMap<Item, _, &bumpalo::Bump> =
471    ///     BiHashMap::with_hasher_in(hasher, &bump);
472    /// assert!(map.is_empty());
473    /// # }
474    /// ```
475    pub fn with_hasher_in(hasher: S, alloc: A) -> Self {
476        Self {
477            items: ItemSet::with_capacity_in(0, alloc.clone()),
478            tables: BiHashMapTables::with_capacity_and_hasher_in(
479                0, hasher, alloc,
480            ),
481        }
482    }
483
484    /// Creates a new, empty `BiHashMap` with the given capacity, hasher, and
485    /// allocator.
486    ///
487    /// Requires the `allocator-api2` feature to be enabled.
488    ///
489    /// # Examples
490    ///
491    /// Using the [`bumpalo`](https://docs.rs/bumpalo) allocator:
492    ///
493    /// ```
494    /// # #[cfg(feature = "allocator-api2")] {
495    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
496    /// use std::collections::hash_map::RandomState;
497    /// # use iddqd_test_utils::bumpalo;
498    ///
499    /// #[derive(Debug, PartialEq, Eq)]
500    /// struct Item {
501    ///     id: u32,
502    ///     name: String,
503    ///     value: i32,
504    /// }
505    ///
506    /// impl BiHashItem for Item {
507    ///     type K1<'a> = u32;
508    ///     type K2<'a> = &'a str;
509    ///
510    ///     fn key1(&self) -> Self::K1<'_> {
511    ///         self.id
512    ///     }
513    ///     fn key2(&self) -> Self::K2<'_> {
514    ///         &self.name
515    ///     }
516    ///     bi_upcast!();
517    /// }
518    ///
519    /// // Define a new allocator.
520    /// let bump = bumpalo::Bump::new();
521    /// let hasher = RandomState::new();
522    /// // Create a new BiHashMap with capacity and hasher using the allocator.
523    /// let map: BiHashMap<Item, _, &bumpalo::Bump> =
524    ///     BiHashMap::with_capacity_and_hasher_in(10, hasher, &bump);
525    /// assert!(map.capacity() >= 10);
526    /// assert!(map.is_empty());
527    /// # }
528    /// ```
529    pub fn with_capacity_and_hasher_in(
530        capacity: usize,
531        hasher: S,
532        alloc: A,
533    ) -> Self {
534        Self {
535            items: ItemSet::with_capacity_in(capacity, alloc.clone()),
536            tables: BiHashMapTables::with_capacity_and_hasher_in(
537                capacity, hasher, alloc,
538            ),
539        }
540    }
541}
542
543impl<T: BiHashItem, S: Clone + BuildHasher, A: Allocator> BiHashMap<T, S, A> {
544    /// Returns the hasher.
545    #[cfg(feature = "daft")]
546    #[inline]
547    pub(crate) fn hasher(&self) -> &S {
548        self.tables.hasher()
549    }
550
551    /// Returns the allocator.
552    ///
553    /// Requires the `allocator-api2` feature to be enabled.
554    ///
555    /// # Examples
556    ///
557    /// Using the [`bumpalo`](https://docs.rs/bumpalo) allocator:
558    ///
559    /// ```
560    /// # #[cfg(all(feature = "default-hasher", feature = "allocator-api2"))] {
561    /// use iddqd::{BiHashMap, BiHashItem, bi_upcast};
562    /// # use iddqd_test_utils::bumpalo;
563    ///
564    /// #[derive(Debug, PartialEq, Eq)]
565    /// struct Item {
566    ///     id: u32,
567    ///     name: String,
568    ///     value: i32,
569    /// }
570    ///
571    /// impl BiHashItem for Item {
572    ///     type K1<'a> = u32;
573    ///     type K2<'a> = &'a str;
574    ///
575    ///     fn key1(&self) -> Self::K1<'_> {
576    ///         self.id
577    ///     }
578    ///     fn key2(&self) -> Self::K2<'_> {
579    ///         &self.name
580    ///     }
581    ///     bi_upcast!();
582    /// }
583    ///
584    /// // Define a new allocator.
585    /// let bump = bumpalo::Bump::new();
586    /// // Create a new BiHashMap using the allocator.
587    /// let map: BiHashMap<Item, _, &bumpalo::Bump> = BiHashMap::new_in(&bump);
588    /// let _allocator = map.allocator();
589    /// # }
590    /// ```
591    #[inline]
592    pub fn allocator(&self) -> &A {
593        self.items.allocator()
594    }
595
596    /// Returns the currently allocated capacity of the map.
597    ///
598    /// # Examples
599    ///
600    /// ```
601    /// # #[cfg(feature = "default-hasher")] {
602    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
603    ///
604    /// #[derive(Debug, PartialEq, Eq)]
605    /// struct Item {
606    ///     id: u32,
607    ///     name: String,
608    ///     value: i32,
609    /// }
610    ///
611    /// impl BiHashItem for Item {
612    ///     type K1<'a> = u32;
613    ///     type K2<'a> = &'a str;
614    ///
615    ///     fn key1(&self) -> Self::K1<'_> {
616    ///         self.id
617    ///     }
618    ///     fn key2(&self) -> Self::K2<'_> {
619    ///         &self.name
620    ///     }
621    ///     bi_upcast!();
622    /// }
623    ///
624    /// let map: BiHashMap<Item> = BiHashMap::with_capacity(10);
625    /// assert!(map.capacity() >= 10);
626    ///
627    /// let empty_map: BiHashMap<Item> = BiHashMap::new();
628    /// assert!(empty_map.capacity() >= 0);
629    /// # }
630    /// ```
631    pub fn capacity(&self) -> usize {
632        // items and tables.capacity might theoretically diverge: use
633        // items.capacity.
634        self.items.capacity()
635    }
636
637    /// Returns true if the map contains no items.
638    ///
639    /// # Examples
640    ///
641    /// ```
642    /// # #[cfg(feature = "default-hasher")] {
643    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
644    ///
645    /// #[derive(Debug, PartialEq, Eq)]
646    /// struct Item {
647    ///     id: u32,
648    ///     name: String,
649    ///     value: i32,
650    /// }
651    ///
652    /// impl BiHashItem for Item {
653    ///     type K1<'a> = u32;
654    ///     type K2<'a> = &'a str;
655    ///
656    ///     fn key1(&self) -> Self::K1<'_> {
657    ///         self.id
658    ///     }
659    ///     fn key2(&self) -> Self::K2<'_> {
660    ///         &self.name
661    ///     }
662    ///     bi_upcast!();
663    /// }
664    ///
665    /// let mut map = BiHashMap::new();
666    /// assert!(map.is_empty());
667    ///
668    /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
669    ///     .unwrap();
670    /// assert!(!map.is_empty());
671    /// # }
672    /// ```
673    #[inline]
674    pub fn is_empty(&self) -> bool {
675        self.items.is_empty()
676    }
677
678    /// Returns the number of items in the map.
679    ///
680    /// # Examples
681    ///
682    /// ```
683    /// # #[cfg(feature = "default-hasher")] {
684    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
685    ///
686    /// #[derive(Debug, PartialEq, Eq)]
687    /// struct Item {
688    ///     id: u32,
689    ///     name: String,
690    ///     value: i32,
691    /// }
692    ///
693    /// impl BiHashItem for Item {
694    ///     type K1<'a> = u32;
695    ///     type K2<'a> = &'a str;
696    ///
697    ///     fn key1(&self) -> Self::K1<'_> {
698    ///         self.id
699    ///     }
700    ///     fn key2(&self) -> Self::K2<'_> {
701    ///         &self.name
702    ///     }
703    ///     bi_upcast!();
704    /// }
705    ///
706    /// let mut map = BiHashMap::new();
707    /// assert_eq!(map.len(), 0);
708    ///
709    /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
710    ///     .unwrap();
711    /// map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
712    ///     .unwrap();
713    /// assert_eq!(map.len(), 2);
714    /// # }
715    /// ```
716    #[inline]
717    pub fn len(&self) -> usize {
718        self.items.len()
719    }
720
721    /// Clears the map, removing all items.
722    ///
723    /// # Examples
724    ///
725    /// ```
726    /// # #[cfg(feature = "default-hasher")] {
727    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
728    ///
729    /// #[derive(Debug, PartialEq, Eq)]
730    /// struct Item {
731    ///     id: u32,
732    ///     name: String,
733    ///     value: i32,
734    /// }
735    ///
736    /// impl BiHashItem for Item {
737    ///     type K1<'a> = u32;
738    ///     type K2<'a> = &'a str;
739    ///
740    ///     fn key1(&self) -> Self::K1<'_> {
741    ///         self.id
742    ///     }
743    ///     fn key2(&self) -> Self::K2<'_> {
744    ///         &self.name
745    ///     }
746    ///     bi_upcast!();
747    /// }
748    ///
749    /// let mut map = BiHashMap::new();
750    /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
751    ///     .unwrap();
752    /// map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
753    ///     .unwrap();
754    /// assert_eq!(map.len(), 2);
755    ///
756    /// map.clear();
757    /// assert!(map.is_empty());
758    /// assert_eq!(map.len(), 0);
759    /// # }
760    /// ```
761    pub fn clear(&mut self) {
762        // Clear the internal indexes before dropping items. This way, if a user
763        // `Drop` panics during `self.items.clear()`, the tables cannot retain
764        // indexes pointing to removed item slots.
765        self.tables.k1_to_item.clear();
766        self.tables.k2_to_item.clear();
767        self.items.clear();
768    }
769
770    /// Reserves capacity for at least `additional` more elements to be inserted
771    /// in the `BiHashMap`. The collection may reserve more space to
772    /// speculatively avoid frequent reallocations. After calling `reserve`,
773    /// capacity will be greater than or equal to `self.len() + additional`.
774    /// Does nothing if capacity is already sufficient.
775    ///
776    /// # Panics
777    ///
778    /// Panics if the new capacity overflows [`isize::MAX`] bytes, and
779    /// [`abort`]s the program in case of an allocation error. Use
780    /// [`try_reserve`](Self::try_reserve) instead if you want to handle memory
781    /// allocation failure.
782    ///
783    /// [`isize::MAX`]: https://doc.rust-lang.org/std/primitive.isize.html
784    /// [`abort`]: https://doc.rust-lang.org/alloc/alloc/fn.handle_alloc_error.html
785    ///
786    /// # Examples
787    ///
788    /// ```
789    /// # #[cfg(feature = "default-hasher")] {
790    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
791    ///
792    /// #[derive(Debug, PartialEq, Eq, Hash)]
793    /// struct Item {
794    ///     id: u32,
795    ///     name: String,
796    /// }
797    ///
798    /// impl BiHashItem for Item {
799    ///     type K1<'a> = u32;
800    ///     type K2<'a> = &'a str;
801    ///     fn key1(&self) -> Self::K1<'_> {
802    ///         self.id
803    ///     }
804    ///     fn key2(&self) -> Self::K2<'_> {
805    ///         &self.name
806    ///     }
807    ///     bi_upcast!();
808    /// }
809    ///
810    /// let mut map: BiHashMap<Item> = BiHashMap::new();
811    /// map.reserve(100);
812    /// assert!(map.capacity() >= 100);
813    /// # }
814    /// ```
815    pub fn reserve(&mut self, additional: usize) {
816        self.items.reserve(additional);
817        self.tables.k1_to_item.reserve(additional);
818        self.tables.k2_to_item.reserve(additional);
819    }
820
821    /// Tries to reserve capacity for at least `additional` more elements to be
822    /// inserted in the `BiHashMap`. The collection may reserve more space to
823    /// speculatively avoid frequent reallocations. After calling `try_reserve`,
824    /// capacity will be greater than or equal to `self.len() + additional` if
825    /// it returns `Ok(())`. Does nothing if capacity is already sufficient.
826    ///
827    /// # Errors
828    ///
829    /// If the capacity overflows, or the allocator reports a failure, then an
830    /// error is returned.
831    ///
832    /// # Notes
833    ///
834    /// If reservation fails partway through, some internal structures may have
835    /// already increased their capacity. The map remains in a valid state but
836    /// may have uneven capacities across its internal structures.
837    ///
838    /// # Examples
839    ///
840    /// ```
841    /// # #[cfg(feature = "default-hasher")] {
842    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
843    ///
844    /// #[derive(Debug, PartialEq, Eq, Hash)]
845    /// struct Item {
846    ///     id: u32,
847    ///     name: String,
848    /// }
849    ///
850    /// impl BiHashItem for Item {
851    ///     type K1<'a> = u32;
852    ///     type K2<'a> = &'a str;
853    ///     fn key1(&self) -> Self::K1<'_> {
854    ///         self.id
855    ///     }
856    ///     fn key2(&self) -> Self::K2<'_> {
857    ///         &self.name
858    ///     }
859    ///     bi_upcast!();
860    /// }
861    ///
862    /// let mut map: BiHashMap<Item> = BiHashMap::new();
863    /// map.try_reserve(100).expect("allocation should succeed");
864    /// assert!(map.capacity() >= 100);
865    /// # }
866    /// ```
867    pub fn try_reserve(
868        &mut self,
869        additional: usize,
870    ) -> Result<(), crate::errors::TryReserveError> {
871        self.items.try_reserve(additional)?;
872        self.tables
873            .k1_to_item
874            .try_reserve(additional)
875            .map_err(crate::errors::TryReserveError::from_hashbrown)?;
876        self.tables
877            .k2_to_item
878            .try_reserve(additional)
879            .map_err(crate::errors::TryReserveError::from_hashbrown)?;
880        Ok(())
881    }
882
883    /// Shrinks the capacity of the map as much as possible. It will drop
884    /// down as much as possible while maintaining the internal rules
885    /// and possibly leaving some space in accordance with the resize policy.
886    ///
887    /// # Examples
888    ///
889    /// ```
890    /// # #[cfg(feature = "default-hasher")] {
891    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
892    ///
893    /// #[derive(Debug, PartialEq, Eq, Hash)]
894    /// struct Item {
895    ///     id: u32,
896    ///     name: String,
897    /// }
898    ///
899    /// impl BiHashItem for Item {
900    ///     type K1<'a> = u32;
901    ///     type K2<'a> = &'a str;
902    ///     fn key1(&self) -> Self::K1<'_> {
903    ///         self.id
904    ///     }
905    ///     fn key2(&self) -> Self::K2<'_> {
906    ///         &self.name
907    ///     }
908    ///     bi_upcast!();
909    /// }
910    ///
911    /// let mut map: BiHashMap<Item> = BiHashMap::with_capacity(100);
912    /// map.insert_unique(Item { id: 1, name: "foo".to_string() }).unwrap();
913    /// map.insert_unique(Item { id: 2, name: "bar".to_string() }).unwrap();
914    /// assert!(map.capacity() >= 100);
915    /// map.shrink_to_fit();
916    /// assert!(map.capacity() >= 2);
917    /// # }
918    /// ```
919    pub fn shrink_to_fit(&mut self) {
920        // Sequence this carefully.
921        //
922        // * First, compact the item set. This does not allocate through A
923        //   (it allocates a small remap buffer through the global allocator),
924        //   and returns a remapper.
925        // * Then, remap the tables using the remapper.
926        // * Finally, shrink the capacities of the tables and items.
927        //
928        // An allocator panic during either capacity shrink leaves the tables
929        // and items already in sync, because remap has already been committed.
930        let remap = self.items.compact();
931        if !remap.is_identity() {
932            self.tables.k1_to_item.remap_indexes(&remap);
933            self.tables.k2_to_item.remap_indexes(&remap);
934        }
935        self.items.shrink_capacity_to_fit();
936        self.tables.k1_to_item.shrink_to_fit();
937        self.tables.k2_to_item.shrink_to_fit();
938    }
939
940    /// Shrinks the capacity of the map with a lower limit. It will drop
941    /// down no lower than the supplied limit while maintaining the internal
942    /// rules and possibly leaving some space in accordance with the resize
943    /// policy.
944    ///
945    /// If the current capacity is less than the lower limit, this is a no-op.
946    ///
947    /// # Examples
948    ///
949    /// ```
950    /// # #[cfg(feature = "default-hasher")] {
951    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
952    ///
953    /// #[derive(Debug, PartialEq, Eq, Hash)]
954    /// struct Item {
955    ///     id: u32,
956    ///     name: String,
957    /// }
958    ///
959    /// impl BiHashItem for Item {
960    ///     type K1<'a> = u32;
961    ///     type K2<'a> = &'a str;
962    ///     fn key1(&self) -> Self::K1<'_> {
963    ///         self.id
964    ///     }
965    ///     fn key2(&self) -> Self::K2<'_> {
966    ///         &self.name
967    ///     }
968    ///     bi_upcast!();
969    /// }
970    ///
971    /// let mut map: BiHashMap<Item> = BiHashMap::with_capacity(100);
972    /// map.insert_unique(Item { id: 1, name: "foo".to_string() }).unwrap();
973    /// map.insert_unique(Item { id: 2, name: "bar".to_string() }).unwrap();
974    /// assert!(map.capacity() >= 100);
975    /// map.shrink_to(10);
976    /// assert!(map.capacity() >= 10);
977    /// map.shrink_to(0);
978    /// assert!(map.capacity() >= 2);
979    /// # }
980    /// ```
981    pub fn shrink_to(&mut self, min_capacity: usize) {
982        // See `shrink_to_fit` for the rationale behind the sequence.
983        let remap = self.items.compact();
984        if !remap.is_identity() {
985            self.tables.k1_to_item.remap_indexes(&remap);
986            self.tables.k2_to_item.remap_indexes(&remap);
987        }
988        self.items.shrink_capacity_to(min_capacity);
989        self.tables.k1_to_item.shrink_to(min_capacity);
990        self.tables.k2_to_item.shrink_to(min_capacity);
991    }
992
993    /// Returns an iterator over all items in the map.
994    ///
995    /// Similar to [`HashMap`], the iteration order is arbitrary and not
996    /// guaranteed to be stable.
997    ///
998    /// [`HashMap`]: std::collections::HashMap
999    /// # Examples
1000    ///
1001    /// ```
1002    /// # #[cfg(feature = "default-hasher")] {
1003    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
1004    ///
1005    /// #[derive(Debug, PartialEq, Eq)]
1006    /// struct Item {
1007    ///     id: u32,
1008    ///     name: String,
1009    ///     value: i32,
1010    /// }
1011    ///
1012    /// impl BiHashItem for Item {
1013    ///     type K1<'a> = u32;
1014    ///     type K2<'a> = &'a str;
1015    ///
1016    ///     fn key1(&self) -> Self::K1<'_> {
1017    ///         self.id
1018    ///     }
1019    ///     fn key2(&self) -> Self::K2<'_> {
1020    ///         &self.name
1021    ///     }
1022    ///     bi_upcast!();
1023    /// }
1024    ///
1025    /// let mut map = BiHashMap::new();
1026    /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
1027    ///     .unwrap();
1028    /// map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
1029    ///     .unwrap();
1030    ///
1031    /// let mut values: Vec<i32> = map.iter().map(|item| item.value).collect();
1032    /// values.sort();
1033    /// assert_eq!(values, vec![42, 99]);
1034    /// # }
1035    /// ```
1036    #[inline]
1037    pub fn iter(&self) -> Iter<'_, T> {
1038        Iter::new(&self.items)
1039    }
1040
1041    /// Iterates over the items in the map, allowing for mutation.
1042    ///
1043    /// Similar to [`HashMap`], the iteration order is arbitrary and not
1044    /// guaranteed to be stable.
1045    ///
1046    /// # Examples
1047    ///
1048    /// ```
1049    /// # #[cfg(feature = "default-hasher")] {
1050    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
1051    ///
1052    /// #[derive(Debug, PartialEq, Eq)]
1053    /// struct Item {
1054    ///     id: u32,
1055    ///     name: String,
1056    ///     value: i32,
1057    /// }
1058    ///
1059    /// impl BiHashItem for Item {
1060    ///     type K1<'a> = u32;
1061    ///     type K2<'a> = &'a str;
1062    ///
1063    ///     fn key1(&self) -> Self::K1<'_> {
1064    ///         self.id
1065    ///     }
1066    ///     fn key2(&self) -> Self::K2<'_> {
1067    ///         &self.name
1068    ///     }
1069    ///     bi_upcast!();
1070    /// }
1071    ///
1072    /// let mut map = BiHashMap::new();
1073    /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
1074    ///     .unwrap();
1075    /// map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
1076    ///     .unwrap();
1077    ///
1078    /// for mut item in map.iter_mut() {
1079    ///     item.value += 10;
1080    /// }
1081    ///
1082    /// assert_eq!(map.get1(&1).unwrap().value, 52);
1083    /// assert_eq!(map.get1(&2).unwrap().value, 109);
1084    /// # }
1085    /// ```
1086    ///
1087    /// [`HashMap`]: std::collections::HashMap
1088    #[inline]
1089    pub fn iter_mut(&mut self) -> IterMut<'_, T, S, A> {
1090        IterMut::new(&self.tables, &mut self.items)
1091    }
1092
1093    /// Checks general invariants of the map.
1094    ///
1095    /// The code below always upholds these invariants, but it's useful to have
1096    /// an explicit check for tests.
1097    #[doc(hidden)]
1098    pub fn validate(
1099        &self,
1100        compactness: ValidateCompact,
1101    ) -> Result<(), ValidationError>
1102    where
1103        T: fmt::Debug,
1104    {
1105        self.validate_structural(compactness)?;
1106
1107        // Check that the indexes are all correct.
1108        //
1109        // Unlike the structural checks, this re-looks up each key through the
1110        // user `Hash`, so it only holds when that `Hash` is lawful.
1111        for (ix, item) in self.items.iter() {
1112            let key1 = item.key1();
1113            let key2 = item.key2();
1114
1115            let Some(ix1) = self.find1_index(&key1) else {
1116                return Err(ValidationError::general(format!(
1117                    "item at index {ix} has no key1 index"
1118                )));
1119            };
1120            let Some(ix2) = self.find2_index(&key2) else {
1121                return Err(ValidationError::general(format!(
1122                    "item at index {ix} has no key2 index"
1123                )));
1124            };
1125
1126            if ix1 != ix || ix2 != ix {
1127                return Err(ValidationError::general(format!(
1128                    "item at index {ix} has inconsistent indexes: {ix1}/{ix2}"
1129                )));
1130            }
1131        }
1132
1133        Ok(())
1134    }
1135
1136    /// Checks the structural invariants of the map:
1137    ///
1138    /// * The item set is well-formed.
1139    /// * Each per-key hash table holds exactly one entry per live item, with no
1140    ///   duplicate `ItemIndex`es.
1141    ///
1142    /// Unlike [`validate`](Self::validate), this does not re-look-up keys
1143    /// through the user `Hash`, so it holds regardless of whether that `Hash`
1144    /// is lawful. A buggy hasher can desync the logical key→item mapping, but
1145    /// it must never break these structural invariants! Doing so would be
1146    /// unsoundness, e.g. duplicate indexes enabling mutable aliasing.
1147    #[doc(hidden)]
1148    pub fn validate_structural(
1149        &self,
1150        compactness: ValidateCompact,
1151    ) -> Result<(), ValidationError> {
1152        self.items.validate(compactness)?;
1153        self.tables.validate(self.len(), compactness)?;
1154        Ok(())
1155    }
1156
1157    /// Inserts a value into the map, removing any conflicting items and
1158    /// returning a list of those items.
1159    ///
1160    /// # Examples
1161    ///
1162    /// ```
1163    /// # #[cfg(feature = "default-hasher")] {
1164    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
1165    ///
1166    /// #[derive(Debug, PartialEq, Eq)]
1167    /// struct Item {
1168    ///     id: u32,
1169    ///     name: String,
1170    ///     value: i32,
1171    /// }
1172    ///
1173    /// impl BiHashItem for Item {
1174    ///     type K1<'a> = u32;
1175    ///     type K2<'a> = &'a str;
1176    ///
1177    ///     fn key1(&self) -> Self::K1<'_> {
1178    ///         self.id
1179    ///     }
1180    ///     fn key2(&self) -> Self::K2<'_> {
1181    ///         &self.name
1182    ///     }
1183    ///     bi_upcast!();
1184    /// }
1185    ///
1186    /// let mut map = BiHashMap::new();
1187    /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
1188    ///     .unwrap();
1189    /// map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
1190    ///     .unwrap();
1191    ///
1192    /// // Insert an item with conflicting key1
1193    /// let removed = map.insert_overwrite(Item {
1194    ///     id: 1,
1195    ///     name: "baz".to_string(),
1196    ///     value: 100,
1197    /// });
1198    /// assert_eq!(removed.len(), 1);
1199    /// assert_eq!(removed[0].name, "foo");
1200    /// assert_eq!(removed[0].value, 42);
1201    ///
1202    /// assert_eq!(map.len(), 2);
1203    /// assert_eq!(map.get1(&1).unwrap().name, "baz");
1204    /// # }
1205    /// ```
1206    #[doc(alias = "insert")]
1207    pub fn insert_overwrite(&mut self, value: T) -> Vec<T> {
1208        let prepared = self.prepare_insert_overwrite(&value);
1209
1210        let mut duplicates = Vec::with_capacity(prepared.duplicate_count());
1211
1212        self.try_reserve_insert_overwrite_commit(
1213            prepared.needs_new_item_slot(),
1214        )
1215        .expect("reserved space successfully");
1216
1217        self.commit_insert_overwrite(value, prepared, &mut duplicates);
1218
1219        duplicates
1220    }
1221
1222    /// Inserts a value into the set, returning an error if any duplicates were
1223    /// added.
1224    ///
1225    /// # Examples
1226    ///
1227    /// ```
1228    /// # #[cfg(feature = "default-hasher")] {
1229    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
1230    ///
1231    /// #[derive(Debug, PartialEq, Eq)]
1232    /// struct Item {
1233    ///     id: u32,
1234    ///     name: String,
1235    ///     value: i32,
1236    /// }
1237    ///
1238    /// impl BiHashItem for Item {
1239    ///     type K1<'a> = u32;
1240    ///     type K2<'a> = &'a str;
1241    ///
1242    ///     fn key1(&self) -> Self::K1<'_> {
1243    ///         self.id
1244    ///     }
1245    ///     fn key2(&self) -> Self::K2<'_> {
1246    ///         &self.name
1247    ///     }
1248    ///     bi_upcast!();
1249    /// }
1250    ///
1251    /// let mut map = BiHashMap::new();
1252    ///
1253    /// // Successful insertion
1254    /// assert!(
1255    ///     map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
1256    ///         .is_ok()
1257    /// );
1258    /// assert!(
1259    ///     map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
1260    ///         .is_ok()
1261    /// );
1262    ///
1263    /// // Duplicate key1
1264    /// assert!(
1265    ///     map.insert_unique(Item { id: 1, name: "baz".to_string(), value: 100 })
1266    ///         .is_err()
1267    /// );
1268    ///
1269    /// // Duplicate key2
1270    /// assert!(
1271    ///     map.insert_unique(Item { id: 3, name: "foo".to_string(), value: 200 })
1272    ///         .is_err()
1273    /// );
1274    /// # }
1275    /// ```
1276    pub fn insert_unique(
1277        &mut self,
1278        value: T,
1279    ) -> Result<(), DuplicateItem<T, &T>> {
1280        let _ = self.insert_unique_impl(value)?;
1281        Ok(())
1282    }
1283
1284    /// Returns true if the map contains a single item that matches both `key1` and `key2`.
1285    ///
1286    /// # Examples
1287    ///
1288    /// ```
1289    /// # #[cfg(feature = "default-hasher")] {
1290    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
1291    ///
1292    /// #[derive(Debug, PartialEq, Eq)]
1293    /// struct Item {
1294    ///     id: u32,
1295    ///     name: String,
1296    ///     value: i32,
1297    /// }
1298    ///
1299    /// impl BiHashItem for Item {
1300    ///     type K1<'a> = u32;
1301    ///     type K2<'a> = &'a str;
1302    ///
1303    ///     fn key1(&self) -> Self::K1<'_> {
1304    ///         self.id
1305    ///     }
1306    ///     fn key2(&self) -> Self::K2<'_> {
1307    ///         &self.name
1308    ///     }
1309    ///     bi_upcast!();
1310    /// }
1311    ///
1312    /// let mut map = BiHashMap::new();
1313    /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 }).unwrap();
1314    /// map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 }).unwrap();
1315    ///
1316    /// assert!(map.contains_key_unique(&1, &"foo"));
1317    /// assert!(map.contains_key_unique(&2, &"bar"));
1318    /// assert!(!map.contains_key_unique(&1, &"bar")); // key1 exists but key2 doesn't match
1319    /// assert!(!map.contains_key_unique(&3, &"baz")); // neither key exists
1320    /// # }
1321    /// ```
1322    pub fn contains_key_unique<'a, Q1, Q2>(
1323        &'a self,
1324        key1: &Q1,
1325        key2: &Q2,
1326    ) -> bool
1327    where
1328        Q1: Hash + Equivalent<T::K1<'a>> + ?Sized,
1329        Q2: Hash + Equivalent<T::K2<'a>> + ?Sized,
1330    {
1331        self.get_unique(key1, key2).is_some()
1332    }
1333
1334    /// Gets a reference to the unique item associated with the given `key1` and
1335    /// `key2`, if it exists.
1336    ///
1337    /// # Examples
1338    ///
1339    /// ```
1340    /// # #[cfg(feature = "default-hasher")] {
1341    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
1342    ///
1343    /// #[derive(Debug, PartialEq, Eq)]
1344    /// struct Item {
1345    ///     id: u32,
1346    ///     name: String,
1347    ///     value: i32,
1348    /// }
1349    ///
1350    /// impl BiHashItem for Item {
1351    ///     type K1<'a> = u32;
1352    ///     type K2<'a> = &'a str;
1353    ///
1354    ///     fn key1(&self) -> Self::K1<'_> {
1355    ///         self.id
1356    ///     }
1357    ///     fn key2(&self) -> Self::K2<'_> {
1358    ///         &self.name
1359    ///     }
1360    ///     bi_upcast!();
1361    /// }
1362    ///
1363    /// let mut map = BiHashMap::new();
1364    /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 }).unwrap();
1365    /// map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 }).unwrap();
1366    ///
1367    /// assert_eq!(map.get_unique(&1, &"foo").unwrap().value, 42);
1368    /// assert_eq!(map.get_unique(&2, &"bar").unwrap().value, 99);
1369    /// assert!(map.get_unique(&1, &"bar").is_none()); // key1 exists but key2 doesn't match
1370    /// assert!(map.get_unique(&3, &"baz").is_none()); // neither key exists
1371    /// # }
1372    /// ```
1373    pub fn get_unique<'a, Q1, Q2>(
1374        &'a self,
1375        key1: &Q1,
1376        key2: &Q2,
1377    ) -> Option<&'a T>
1378    where
1379        Q1: Hash + Equivalent<T::K1<'a>> + ?Sized,
1380        Q2: Hash + Equivalent<T::K2<'a>> + ?Sized,
1381    {
1382        let index = self.find1_index(key1)?;
1383        let item = &self.items[index];
1384        if key2.equivalent(&item.key2()) { Some(item) } else { None }
1385    }
1386
1387    /// Gets a mutable reference to the unique item associated with the given
1388    /// `key1` and `key2`, if it exists.
1389    pub fn get_mut_unique<'a, Q1, Q2>(
1390        &'a mut self,
1391        key1: &Q1,
1392        key2: &Q2,
1393    ) -> Option<RefMut<'a, T, S>>
1394    where
1395        Q1: Hash + Equivalent<T::K1<'a>> + ?Sized,
1396        Q2: Hash + Equivalent<T::K2<'a>> + ?Sized,
1397    {
1398        let (dormant_map, index) = {
1399            let (map, dormant_map) = DormantMutRef::new(self);
1400            let index = map.find1_index(key1)?;
1401            // Check key2 match before proceeding
1402            if !key2.equivalent(&map.items[index].key2()) {
1403                return None;
1404            }
1405            (dormant_map, index)
1406        };
1407
1408        // SAFETY: `map` is not used after this point.
1409        let awakened_map = unsafe { dormant_map.awaken() };
1410        let item = &mut awakened_map.items[index];
1411        let state = awakened_map.tables.state.clone();
1412        let hashes =
1413            awakened_map.tables.make_hashes::<T>(&item.key1(), &item.key2());
1414        Some(RefMut::new(state, hashes, item))
1415    }
1416
1417    /// Removes the item uniquely identified by `key1` and `key2`, if it exists.
1418    pub fn remove_unique<'a, Q1, Q2>(
1419        &'a mut self,
1420        key1: &Q1,
1421        key2: &Q2,
1422    ) -> Option<T>
1423    where
1424        Q1: Hash + Equivalent<T::K1<'a>> + ?Sized,
1425        Q2: Hash + Equivalent<T::K2<'a>> + ?Sized,
1426    {
1427        let (dormant_map, remove_index) = {
1428            let (map, dormant_map) = DormantMutRef::new(self);
1429            let remove_index = map.find1_index(key1)?;
1430            if !key2.equivalent(&map.items[remove_index].key2()) {
1431                return None;
1432            }
1433            (dormant_map, remove_index)
1434        };
1435
1436        // SAFETY: `map` is not used after this point.
1437        let awakened_map = unsafe { dormant_map.awaken() };
1438
1439        awakened_map.remove_by_index(remove_index)
1440    }
1441
1442    /// Returns true if the map contains the given `key1`.
1443    ///
1444    /// # Examples
1445    ///
1446    /// ```
1447    /// # #[cfg(feature = "default-hasher")] {
1448    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
1449    ///
1450    /// #[derive(Debug, PartialEq, Eq)]
1451    /// struct Item {
1452    ///     id: u32,
1453    ///     name: String,
1454    ///     value: i32,
1455    /// }
1456    ///
1457    /// impl BiHashItem for Item {
1458    ///     type K1<'a> = u32;
1459    ///     type K2<'a> = &'a str;
1460    ///
1461    ///     fn key1(&self) -> Self::K1<'_> {
1462    ///         self.id
1463    ///     }
1464    ///     fn key2(&self) -> Self::K2<'_> {
1465    ///         &self.name
1466    ///     }
1467    ///     bi_upcast!();
1468    /// }
1469    ///
1470    /// let mut map = BiHashMap::new();
1471    /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
1472    ///     .unwrap();
1473    /// map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
1474    ///     .unwrap();
1475    ///
1476    /// assert!(map.contains_key1(&1));
1477    /// assert!(map.contains_key1(&2));
1478    /// assert!(!map.contains_key1(&3));
1479    /// # }
1480    /// ```
1481    pub fn contains_key1<'a, Q>(&'a self, key1: &Q) -> bool
1482    where
1483        Q: Hash + Equivalent<T::K1<'a>> + ?Sized,
1484    {
1485        self.find1_index(key1).is_some()
1486    }
1487
1488    /// Gets a reference to the value associated with the given `key1`.
1489    ///
1490    /// # Examples
1491    ///
1492    /// ```
1493    /// # #[cfg(feature = "default-hasher")] {
1494    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
1495    ///
1496    /// #[derive(Debug, PartialEq, Eq)]
1497    /// struct Item {
1498    ///     id: u32,
1499    ///     name: String,
1500    ///     value: i32,
1501    /// }
1502    ///
1503    /// impl BiHashItem for Item {
1504    ///     type K1<'a> = u32;
1505    ///     type K2<'a> = &'a str;
1506    ///
1507    ///     fn key1(&self) -> Self::K1<'_> {
1508    ///         self.id
1509    ///     }
1510    ///     fn key2(&self) -> Self::K2<'_> {
1511    ///         &self.name
1512    ///     }
1513    ///     bi_upcast!();
1514    /// }
1515    ///
1516    /// let mut map = BiHashMap::new();
1517    /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
1518    ///     .unwrap();
1519    /// map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
1520    ///     .unwrap();
1521    ///
1522    /// assert_eq!(map.get1(&1).unwrap().value, 42);
1523    /// assert_eq!(map.get1(&2).unwrap().value, 99);
1524    /// assert!(map.get1(&3).is_none());
1525    /// # }
1526    /// ```
1527    pub fn get1<'a, Q>(&'a self, key1: &Q) -> Option<&'a T>
1528    where
1529        Q: Hash + Equivalent<T::K1<'a>> + ?Sized,
1530    {
1531        self.find1(key1)
1532    }
1533
1534    /// Gets a mutable reference to the value associated with the given `key1`.
1535    pub fn get1_mut<'a, Q>(&'a mut self, key1: &Q) -> Option<RefMut<'a, T, S>>
1536    where
1537        Q: Hash + Equivalent<T::K1<'a>> + ?Sized,
1538    {
1539        let (dormant_map, index) = {
1540            let (map, dormant_map) = DormantMutRef::new(self);
1541            let index = map.find1_index(key1)?;
1542            (dormant_map, index)
1543        };
1544
1545        // SAFETY: `map` is not used after this point.
1546        let awakened_map = unsafe { dormant_map.awaken() };
1547        let item = &mut awakened_map.items[index];
1548        let state = awakened_map.tables.state.clone();
1549        let hashes =
1550            awakened_map.tables.make_hashes::<T>(&item.key1(), &item.key2());
1551        Some(RefMut::new(state, hashes, item))
1552    }
1553
1554    /// Removes an item from the map by its `key1`.
1555    ///
1556    /// # Examples
1557    ///
1558    /// ```
1559    /// # #[cfg(feature = "default-hasher")] {
1560    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
1561    ///
1562    /// #[derive(Debug, PartialEq, Eq)]
1563    /// struct Item {
1564    ///     id: u32,
1565    ///     name: String,
1566    ///     value: i32,
1567    /// }
1568    ///
1569    /// impl BiHashItem for Item {
1570    ///     type K1<'a> = u32;
1571    ///     type K2<'a> = &'a str;
1572    ///
1573    ///     fn key1(&self) -> Self::K1<'_> {
1574    ///         self.id
1575    ///     }
1576    ///     fn key2(&self) -> Self::K2<'_> {
1577    ///         &self.name
1578    ///     }
1579    ///     bi_upcast!();
1580    /// }
1581    ///
1582    /// let mut map = BiHashMap::new();
1583    /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
1584    ///     .unwrap();
1585    /// map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
1586    ///     .unwrap();
1587    ///
1588    /// let removed = map.remove1(&1);
1589    /// assert_eq!(removed.unwrap().value, 42);
1590    /// assert_eq!(map.len(), 1);
1591    /// assert!(map.get1(&1).is_none());
1592    /// assert!(map.remove1(&3).is_none());
1593    /// # }
1594    /// ```
1595    pub fn remove1<'a, Q>(&'a mut self, key1: &Q) -> Option<T>
1596    where
1597        Q: Hash + Equivalent<T::K1<'a>> + ?Sized,
1598    {
1599        let (dormant_map, remove_index) = {
1600            let (map, dormant_map) = DormantMutRef::new(self);
1601            let remove_index = map.find1_index(key1)?;
1602            (dormant_map, remove_index)
1603        };
1604
1605        // SAFETY: `map` is not used after this point.
1606        let awakened_map = unsafe { dormant_map.awaken() };
1607
1608        awakened_map.remove_by_index(remove_index)
1609    }
1610
1611    /// Returns true if the map contains the given `key2`.
1612    ///
1613    /// # Examples
1614    ///
1615    /// ```
1616    /// # #[cfg(feature = "default-hasher")] {
1617    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
1618    ///
1619    /// #[derive(Debug, PartialEq, Eq)]
1620    /// struct Item {
1621    ///     id: u32,
1622    ///     name: String,
1623    ///     value: i32,
1624    /// }
1625    ///
1626    /// impl BiHashItem for Item {
1627    ///     type K1<'a> = u32;
1628    ///     type K2<'a> = &'a str;
1629    ///
1630    ///     fn key1(&self) -> Self::K1<'_> {
1631    ///         self.id
1632    ///     }
1633    ///     fn key2(&self) -> Self::K2<'_> {
1634    ///         &self.name
1635    ///     }
1636    ///     bi_upcast!();
1637    /// }
1638    ///
1639    /// let mut map = BiHashMap::new();
1640    /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
1641    ///     .unwrap();
1642    /// map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
1643    ///     .unwrap();
1644    ///
1645    /// assert!(map.contains_key2(&"foo"));
1646    /// assert!(map.contains_key2(&"bar"));
1647    /// assert!(!map.contains_key2(&"baz"));
1648    /// # }
1649    /// ```
1650    pub fn contains_key2<'a, Q>(&'a self, key2: &Q) -> bool
1651    where
1652        Q: Hash + Equivalent<T::K2<'a>> + ?Sized,
1653    {
1654        self.find2_index(key2).is_some()
1655    }
1656
1657    /// Gets a reference to the value associated with the given `key2`.
1658    ///
1659    /// # Examples
1660    ///
1661    /// ```
1662    /// # #[cfg(feature = "default-hasher")] {
1663    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
1664    ///
1665    /// #[derive(Debug, PartialEq, Eq)]
1666    /// struct Item {
1667    ///     id: u32,
1668    ///     name: String,
1669    ///     value: i32,
1670    /// }
1671    ///
1672    /// impl BiHashItem for Item {
1673    ///     type K1<'a> = u32;
1674    ///     type K2<'a> = &'a str;
1675    ///
1676    ///     fn key1(&self) -> Self::K1<'_> {
1677    ///         self.id
1678    ///     }
1679    ///     fn key2(&self) -> Self::K2<'_> {
1680    ///         &self.name
1681    ///     }
1682    ///     bi_upcast!();
1683    /// }
1684    ///
1685    /// let mut map = BiHashMap::new();
1686    /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
1687    ///     .unwrap();
1688    /// map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
1689    ///     .unwrap();
1690    ///
1691    /// assert_eq!(map.get2(&"foo").unwrap().value, 42);
1692    /// assert_eq!(map.get2(&"bar").unwrap().value, 99);
1693    /// assert!(map.get2(&"baz").is_none());
1694    /// # }
1695    /// ```
1696    pub fn get2<'a, Q>(&'a self, key2: &Q) -> Option<&'a T>
1697    where
1698        Q: Hash + Equivalent<T::K2<'a>> + ?Sized,
1699    {
1700        self.find2(key2)
1701    }
1702
1703    /// Gets a mutable reference to the value associated with the given `key2`.
1704    ///
1705    /// # Examples
1706    ///
1707    /// ```
1708    /// # #[cfg(feature = "default-hasher")] {
1709    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
1710    ///
1711    /// #[derive(Debug, PartialEq, Eq)]
1712    /// struct Item {
1713    ///     id: u32,
1714    ///     name: String,
1715    ///     value: i32,
1716    /// }
1717    ///
1718    /// impl BiHashItem for Item {
1719    ///     type K1<'a> = u32;
1720    ///     type K2<'a> = &'a str;
1721    ///
1722    ///     fn key1(&self) -> Self::K1<'_> {
1723    ///         self.id
1724    ///     }
1725    ///     fn key2(&self) -> Self::K2<'_> {
1726    ///         &self.name
1727    ///     }
1728    ///     bi_upcast!();
1729    /// }
1730    ///
1731    /// let mut map = BiHashMap::new();
1732    /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
1733    ///     .unwrap();
1734    ///
1735    /// if let Some(mut item_ref) = map.get2_mut(&"foo") {
1736    ///     item_ref.value = 100;
1737    /// }
1738    ///
1739    /// assert_eq!(map.get2(&"foo").unwrap().value, 100);
1740    /// # }
1741    /// ```
1742    pub fn get2_mut<'a, Q>(&'a mut self, key2: &Q) -> Option<RefMut<'a, T, S>>
1743    where
1744        Q: Hash + Equivalent<T::K2<'a>> + ?Sized,
1745    {
1746        let (dormant_map, index) = {
1747            let (map, dormant_map) = DormantMutRef::new(self);
1748            let index = map.find2_index(key2)?;
1749            (dormant_map, index)
1750        };
1751
1752        // SAFETY: `map` is not used after this point.
1753        let awakened_map = unsafe { dormant_map.awaken() };
1754        let item = &mut awakened_map.items[index];
1755        let state = awakened_map.tables.state.clone();
1756        let hashes =
1757            awakened_map.tables.make_hashes::<T>(&item.key1(), &item.key2());
1758        Some(RefMut::new(state, hashes, item))
1759    }
1760
1761    /// Removes an item from the map by its `key2`.
1762    ///
1763    /// # Examples
1764    ///
1765    /// ```
1766    /// # #[cfg(feature = "default-hasher")] {
1767    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
1768    ///
1769    /// #[derive(Debug, PartialEq, Eq)]
1770    /// struct Item {
1771    ///     id: u32,
1772    ///     name: String,
1773    ///     value: i32,
1774    /// }
1775    ///
1776    /// impl BiHashItem for Item {
1777    ///     type K1<'a> = u32;
1778    ///     type K2<'a> = &'a str;
1779    ///
1780    ///     fn key1(&self) -> Self::K1<'_> {
1781    ///         self.id
1782    ///     }
1783    ///     fn key2(&self) -> Self::K2<'_> {
1784    ///         &self.name
1785    ///     }
1786    ///     bi_upcast!();
1787    /// }
1788    ///
1789    /// let mut map = BiHashMap::new();
1790    /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
1791    ///     .unwrap();
1792    /// map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
1793    ///     .unwrap();
1794    ///
1795    /// let removed = map.remove2(&"foo");
1796    /// assert_eq!(removed.unwrap().value, 42);
1797    /// assert_eq!(map.len(), 1);
1798    /// assert!(map.get2(&"foo").is_none());
1799    /// assert!(map.remove2(&"baz").is_none());
1800    /// # }
1801    /// ```
1802    pub fn remove2<'a, Q>(&'a mut self, key2: &Q) -> Option<T>
1803    where
1804        Q: Hash + Equivalent<T::K2<'a>> + ?Sized,
1805    {
1806        let (dormant_map, remove_index) = {
1807            let (map, dormant_map) = DormantMutRef::new(self);
1808            let remove_index = map.find2_index(key2)?;
1809            (dormant_map, remove_index)
1810        };
1811
1812        // SAFETY: `map` is not used after this point.
1813        let awakened_map = unsafe { dormant_map.awaken() };
1814
1815        awakened_map.remove_by_index(remove_index)
1816    }
1817
1818    /// Retrieves an entry by its keys.
1819    ///
1820    /// Due to borrow checker limitations, this always accepts owned keys rather
1821    /// than a borrowed form of them.
1822    ///
1823    /// # Differences from single-key entries
1824    ///
1825    /// The [`Entry`] returned by this method differs from those provided
1826    /// for the other map types, because it is possible for one of the two keys
1827    /// provided to correspond to an existing entry, while the other does not.
1828    ///
1829    /// For more information, and examples covering non-unique entries, see the
1830    /// type-level documentation for [`Entry`].
1831    ///
1832    /// # Examples
1833    ///
1834    /// ```
1835    /// # #[cfg(feature = "default-hasher")] {
1836    /// use iddqd::{BiHashItem, BiHashMap, bi_hash_map, bi_upcast};
1837    ///
1838    /// #[derive(Debug, PartialEq, Eq)]
1839    /// struct Item {
1840    ///     id: u32,
1841    ///     name: String,
1842    ///     value: i32,
1843    /// }
1844    ///
1845    /// impl BiHashItem for Item {
1846    ///     type K1<'a> = u32;
1847    ///     type K2<'a> = &'a str;
1848    ///
1849    ///     fn key1(&self) -> Self::K1<'_> {
1850    ///         self.id
1851    ///     }
1852    ///     fn key2(&self) -> Self::K2<'_> {
1853    ///         &self.name
1854    ///     }
1855    ///     bi_upcast!();
1856    /// }
1857    ///
1858    /// let mut map = BiHashMap::new();
1859    /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
1860    ///     .unwrap();
1861    ///
1862    /// // Get an existing entry.
1863    /// match map.entry(1, "foo") {
1864    ///     bi_hash_map::Entry::Occupied(entry) => {
1865    ///         assert_eq!(entry.get().as_unique().unwrap().value, 42);
1866    ///     }
1867    ///     bi_hash_map::Entry::Vacant(_) => panic!("Should be occupied"),
1868    /// }
1869    ///
1870    /// // Try to get a non-existing entry.
1871    /// match map.entry(2, "bar") {
1872    ///     bi_hash_map::Entry::Occupied(_) => panic!("Should be vacant"),
1873    ///     bi_hash_map::Entry::Vacant(entry) => {
1874    ///         entry.insert(Item { id: 2, name: "bar".to_string(), value: 99 });
1875    ///     }
1876    /// }
1877    ///
1878    /// assert_eq!(map.len(), 2);
1879    /// # }
1880    /// ```
1881    ///
1882    /// For an expanded example, see the type-level documentation for [`Entry`].
1883    pub fn entry<'a>(
1884        &'a mut self,
1885        key1: T::K1<'_>,
1886        key2: T::K2<'_>,
1887    ) -> Entry<'a, T, S, A> {
1888        // Why does this always take owned keys? Well, it would seem like we
1889        // should be able to pass in any Q1 and Q2 that are equivalent. That
1890        // results in *this* code compiling fine, but callers have trouble using
1891        // it because the borrow checker believes the keys are borrowed for the
1892        // full 'a rather than a shorter lifetime.
1893        //
1894        // By accepting owned keys, we can use the upcast functions to convert
1895        // them to a shorter lifetime (so this function accepts T::K1<'_> rather
1896        // than T::K1<'a>).
1897        //
1898        // Really, the solution here is to allow GATs to require covariant
1899        // parameters. If that were allowed, the borrow checker should be able
1900        // to figure out that keys don't need to be borrowed for the full 'a,
1901        // just for some shorter lifetime.
1902        let (map, dormant_map) = DormantMutRef::new(self);
1903        let key1 = T::upcast_key1(key1);
1904        let key2 = T::upcast_key2(key2);
1905        let (index1, index2) = {
1906            // index1 and index2 are explicitly typed to show that it has a
1907            // trivial Drop impl that doesn't capture anything from map.
1908            let index1: Option<ItemIndex> = map.tables.k1_to_item.find_index(
1909                &map.tables.state,
1910                &key1,
1911                |index| map.items[index].key1(),
1912            );
1913            let index2: Option<ItemIndex> = map.tables.k2_to_item.find_index(
1914                &map.tables.state,
1915                &key2,
1916                |index| map.items[index].key2(),
1917            );
1918            (index1, index2)
1919        };
1920
1921        match (index1, index2) {
1922            (Some(index1), Some(index2)) if index1 == index2 => {
1923                // The item is already in the map.
1924                drop(key1);
1925                Entry::Occupied(
1926                    // SAFETY: `map` is not used after this point.
1927                    unsafe {
1928                        OccupiedEntry::new(
1929                            dormant_map,
1930                            EntryIndexes::Unique(index1),
1931                        )
1932                    },
1933                )
1934            }
1935            (None, None) => {
1936                let hashes = map.tables.make_hashes::<T>(&key1, &key2);
1937                Entry::Vacant(
1938                    // SAFETY: `map` is not used after this point.
1939                    unsafe { VacantEntry::new(dormant_map, hashes) },
1940                )
1941            }
1942            (index1, index2) => Entry::Occupied(
1943                // SAFETY: `map` is not used after this point.
1944                unsafe {
1945                    OccupiedEntry::new(
1946                        dormant_map,
1947                        EntryIndexes::NonUnique { index1, index2 },
1948                    )
1949                },
1950            ),
1951        }
1952    }
1953
1954    /// Retains only the elements specified by the predicate.
1955    ///
1956    /// In other words, remove all items `T` for which `f(RefMut<T>)` returns
1957    /// false. The elements are visited in an arbitrary order.
1958    ///
1959    /// # Examples
1960    ///
1961    /// ```
1962    /// # #[cfg(feature = "default-hasher")] {
1963    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
1964    ///
1965    /// #[derive(Debug, PartialEq, Eq, Hash)]
1966    /// struct Item {
1967    ///     id: u32,
1968    ///     name: String,
1969    ///     value: u32,
1970    /// }
1971    ///
1972    /// impl BiHashItem for Item {
1973    ///     type K1<'a> = u32;
1974    ///     type K2<'a> = &'a str;
1975    ///
1976    ///     fn key1(&self) -> Self::K1<'_> {
1977    ///         self.id
1978    ///     }
1979    ///     fn key2(&self) -> Self::K2<'_> {
1980    ///         &self.name
1981    ///     }
1982    ///
1983    ///     bi_upcast!();
1984    /// }
1985    ///
1986    /// let mut map = BiHashMap::new();
1987    /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
1988    ///     .unwrap();
1989    /// map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 20 })
1990    ///     .unwrap();
1991    /// map.insert_unique(Item { id: 3, name: "baz".to_string(), value: 99 })
1992    ///     .unwrap();
1993    ///
1994    /// // Retain only items where value is greater than 30
1995    /// map.retain(|item| item.value > 30);
1996    ///
1997    /// assert_eq!(map.len(), 2);
1998    /// assert_eq!(map.get1(&1).unwrap().value, 42);
1999    /// assert_eq!(map.get1(&3).unwrap().value, 99);
2000    /// assert!(map.get1(&2).is_none());
2001    /// # }
2002    /// ```
2003    pub fn retain<'a, F>(&'a mut self, mut f: F)
2004    where
2005        F: for<'b> FnMut(RefMut<'b, T, S>) -> bool,
2006    {
2007        let hash_state = self.tables.state.clone();
2008        let (_, mut dormant_items) = DormantMutRef::new(&mut self.items);
2009        let mut removed_item = None;
2010
2011        self.tables.k1_to_item.retain(|index| {
2012            // Drop the previously-removed item here, at the top of the next
2013            // iteration.
2014            //
2015            // By now, the prior `k1_to_item` entry has been erased, so if
2016            // `drop` below panics, `k1_to_item`, `k2_to_item`, and `items`
2017            // remain in sync. Dropping the item at the end of the prior
2018            // iteration would unwind before the table erased the entry, leaving
2019            // `k1_to_item` pointing at a slot we already removed from `items`
2020            // and `k2_to_item`.
2021            drop(removed_item.take());
2022
2023            let (item, dormant_items) = {
2024                // SAFETY: All uses of `items` ended in the previous iteration.
2025                let items = unsafe { dormant_items.reborrow() };
2026                let (items, dormant_items) = DormantMutRef::new(items);
2027                let item: &'a mut T = items
2028                    .get_mut(index)
2029                    .expect("all indexes are present in self.items");
2030                (item, dormant_items)
2031            };
2032
2033            let (hashes, dormant_item) = {
2034                let (item, dormant_item): (&'a mut T, _) =
2035                    DormantMutRef::new(item);
2036                // Use T::k1(item) rather than item.key() to force the key
2037                // trait function to be called for T rather than &mut T.
2038                let key1 = T::key1(item);
2039                let key2 = T::key2(item);
2040                let hash1 = hash_state.hash_one(key1);
2041                let hash2 = hash_state.hash_one(key2);
2042                ([MapHash::new(hash1), MapHash::new(hash2)], dormant_item)
2043            };
2044
2045            let hash2 = hashes[1].hash();
2046            let retain = {
2047                // SAFETY: The original item is no longer used after the second
2048                // block above. dormant_items, from which item is derived, is
2049                // currently dormant.
2050                let item = unsafe { dormant_item.awaken() };
2051
2052                let ref_mut = RefMut::new(hash_state.clone(), hashes, item);
2053                f(ref_mut)
2054            };
2055
2056            if retain {
2057                true
2058            } else {
2059                let k2_entry = self
2060                    .tables
2061                    .k2_to_item
2062                    .find_entry_by_hash(hash2, |map2_index| {
2063                        map2_index == index
2064                    });
2065                match k2_entry {
2066                    Ok(entry) => {
2067                        entry.remove();
2068                    }
2069                    Err(_) => {
2070                        self.tables.k2_to_item.remove_by_index(index);
2071                    }
2072                }
2073
2074                // SAFETY: The original items is no longer used after the first
2075                // block above, and item + dormant_item have been dropped after
2076                // being used above. The k2 work between them borrows only
2077                // `self.tables.k2_to_item`, which is disjoint from
2078                // `self.items`.
2079                let items = unsafe { dormant_items.awaken() };
2080                removed_item = Some(
2081                    items
2082                        .remove(index)
2083                        .expect("all indexes are present in self.items"),
2084                );
2085
2086                false
2087            }
2088        });
2089
2090        // Anything in `removed_item` is implicitly dropped now.
2091    }
2092
2093    fn find1<'a, Q>(&'a self, k: &Q) -> Option<&'a T>
2094    where
2095        Q: Hash + Equivalent<T::K1<'a>> + ?Sized,
2096    {
2097        self.find1_index(k).map(|ix| &self.items[ix])
2098    }
2099
2100    fn find1_index<'a, Q>(&'a self, k: &Q) -> Option<ItemIndex>
2101    where
2102        Q: Hash + Equivalent<T::K1<'a>> + ?Sized,
2103    {
2104        self.tables
2105            .k1_to_item
2106            .find_index(&self.tables.state, k, |index| self.items[index].key1())
2107    }
2108
2109    fn find2<'a, Q>(&'a self, k: &Q) -> Option<&'a T>
2110    where
2111        Q: Hash + Equivalent<T::K2<'a>> + ?Sized,
2112    {
2113        self.find2_index(k).map(|ix| &self.items[ix])
2114    }
2115
2116    fn find2_index<'a, Q>(&'a self, k: &Q) -> Option<ItemIndex>
2117    where
2118        Q: Hash + Equivalent<T::K2<'a>> + ?Sized,
2119    {
2120        self.tables
2121            .k2_to_item
2122            .find_index(&self.tables.state, k, |index| self.items[index].key2())
2123    }
2124
2125    fn prepare_insert_overwrite(&self, value: &T) -> PreparedInsertOverwrite {
2126        let key1 = value.key1();
2127        let key2 = value.key2();
2128
2129        let index1 = self.find1_index(&key1);
2130        let index2 = self.find2_index(&key2);
2131        let hashes = self.tables.make_hashes::<T>(&key1, &key2);
2132
2133        let duplicates =
2134            PreparedDuplicate::from_indexes([index1, index2], |index| {
2135                self.prepare_duplicate(index)
2136            });
2137
2138        PreparedInsertOverwrite { index1, index2, duplicates, hashes }
2139    }
2140
2141    fn prepare_entry_index_removal(
2142        &self,
2143        indexes: EntryIndexes,
2144    ) -> Vec<PreparedDuplicate> {
2145        match indexes {
2146            EntryIndexes::Unique(index) => {
2147                PreparedDuplicate::from_indexes([Some(index)], |index| {
2148                    self.prepare_duplicate(index)
2149                })
2150            }
2151            EntryIndexes::NonUnique { index1, index2 } => {
2152                PreparedDuplicate::from_indexes([index1, index2], |index| {
2153                    self.prepare_duplicate(index)
2154                })
2155            }
2156        }
2157    }
2158
2159    fn prepare_duplicate(&self, index: ItemIndex) -> PreparedDuplicate {
2160        let item = &self.items[index];
2161        let key1 = item.key1();
2162        let key2 = item.key2();
2163        let hashes = self.tables.make_hashes::<T>(&key1, &key2);
2164
2165        PreparedDuplicate { index, hashes }
2166    }
2167
2168    fn try_reserve_insert_overwrite_commit(
2169        &mut self,
2170        needs_new_item_slot: bool,
2171    ) -> Result<(), TryReserveError> {
2172        if needs_new_item_slot {
2173            self.items.try_reserve(1)?;
2174        }
2175
2176        self.tables
2177            .k1_to_item
2178            .try_reserve(1)
2179            .map_err(TryReserveError::from_hashbrown)?;
2180        self.tables
2181            .k2_to_item
2182            .try_reserve(1)
2183            .map_err(TryReserveError::from_hashbrown)?;
2184
2185        Ok(())
2186    }
2187
2188    fn commit_insert_overwrite(
2189        &mut self,
2190        value: T,
2191        prepared: PreparedInsertOverwrite,
2192        duplicates: &mut Vec<T>,
2193    ) -> ItemIndex {
2194        // From here until insertion completes, do not call user code or
2195        // allocate. The caller prepared hashes/indexes and reserved capacity.
2196        for duplicate in prepared.duplicates {
2197            duplicates.push(
2198                self.remove_duplicate(duplicate)
2199                    .expect("duplicate index was prepared"),
2200            );
2201        }
2202
2203        self.insert_unique_with_prepared_hashes(value, prepared.hashes)
2204    }
2205
2206    fn insert_unique_with_prepared_hashes(
2207        &mut self,
2208        value: T,
2209        hashes: [MapHash; 2],
2210    ) -> ItemIndex {
2211        let [hash1, hash2] = hashes;
2212        let next_index = self.items.assert_can_grow().insert(value);
2213
2214        self.tables.k1_to_item.insert_prehashed_unchecked(hash1, next_index);
2215        self.tables.k2_to_item.insert_prehashed_unchecked(hash2, next_index);
2216
2217        next_index
2218    }
2219
2220    pub(super) fn get_by_entry_index(
2221        &self,
2222        indexes: EntryIndexes,
2223    ) -> OccupiedEntryRef<'_, T> {
2224        match indexes {
2225            EntryIndexes::Unique(index) => OccupiedEntryRef::Unique(
2226                self.items.get(index).expect("index is valid"),
2227            ),
2228            EntryIndexes::NonUnique { index1, index2 } => {
2229                let by_key1 = index1
2230                    .map(|k| self.items.get(k).expect("key1 index is valid"));
2231                let by_key2 = index2
2232                    .map(|k| self.items.get(k).expect("key2 index is valid"));
2233                OccupiedEntryRef::NonUnique { by_key1, by_key2 }
2234            }
2235        }
2236    }
2237
2238    pub(super) fn get_by_entry_index_mut(
2239        &mut self,
2240        indexes: EntryIndexes,
2241    ) -> OccupiedEntryMut<'_, T, S> {
2242        match indexes.disjoint_keys() {
2243            DisjointKeys::Unique(index) => {
2244                let item = self.items.get_mut(index).expect("index is valid");
2245                let state = self.tables.state.clone();
2246                let hashes =
2247                    self.tables.make_hashes::<T>(&item.key1(), &item.key2());
2248                OccupiedEntryMut::Unique(RefMut::new(state, hashes, item))
2249            }
2250            DisjointKeys::Key1(index1) => {
2251                let item =
2252                    self.items.get_mut(index1).expect("key1 index is valid");
2253                let state = self.tables.state.clone();
2254                let hashes =
2255                    self.tables.make_hashes::<T>(&item.key1(), &item.key2());
2256                OccupiedEntryMut::NonUnique {
2257                    by_key1: Some(RefMut::new(state, hashes, item)),
2258                    by_key2: None,
2259                }
2260            }
2261            DisjointKeys::Key2(index2) => {
2262                let item =
2263                    self.items.get_mut(index2).expect("key2 index is valid");
2264                let state = self.tables.state.clone();
2265                let hashes =
2266                    self.tables.make_hashes::<T>(&item.key1(), &item.key2());
2267                OccupiedEntryMut::NonUnique {
2268                    by_key1: None,
2269                    by_key2: Some(RefMut::new(state, hashes, item)),
2270                }
2271            }
2272            DisjointKeys::Key12(indexes) => {
2273                let state = self.tables.state.clone();
2274                let mut items = self.items.get_disjoint_mut(indexes);
2275                let item1 = items[0].take().expect("key1 index is valid");
2276                let item2 = items[1].take().expect("key2 index is valid");
2277                let hashes1 =
2278                    self.tables.make_hashes::<T>(&item1.key1(), &item1.key2());
2279                let hashes2 =
2280                    self.tables.make_hashes::<T>(&item2.key1(), &item2.key2());
2281
2282                OccupiedEntryMut::NonUnique {
2283                    by_key1: Some(RefMut::new(state.clone(), hashes1, item1)),
2284                    by_key2: Some(RefMut::new(state, hashes2, item2)),
2285                }
2286            }
2287        }
2288    }
2289
2290    pub(super) fn get_by_index_mut(
2291        &mut self,
2292        index: ItemIndex,
2293    ) -> Option<RefMut<'_, T, S>> {
2294        let borrowed = self.items.get_mut(index)?;
2295        let state = self.tables.state.clone();
2296        let hashes =
2297            self.tables.make_hashes::<T>(&borrowed.key1(), &borrowed.key2());
2298        let item = &mut self.items[index];
2299        Some(RefMut::new(state, hashes, item))
2300    }
2301
2302    pub(super) fn insert_unique_impl(
2303        &mut self,
2304        value: T,
2305    ) -> Result<ItemIndex, DuplicateItem<T, &T>> {
2306        let mut duplicates = BTreeSet::new();
2307
2308        // Check for duplicates *before* inserting the new item, because we
2309        // don't want to partially insert the new item and then have to roll
2310        // back.
2311        let state = &self.tables.state;
2312        let (e1, e2) = {
2313            let k1 = value.key1();
2314            let k2 = value.key2();
2315
2316            let e1 = detect_dup_or_insert(
2317                self.tables
2318                    .k1_to_item
2319                    .entry(state, k1, |index| self.items[index].key1()),
2320                &mut duplicates,
2321            );
2322            let e2 = detect_dup_or_insert(
2323                self.tables
2324                    .k2_to_item
2325                    .entry(state, k2, |index| self.items[index].key2()),
2326                &mut duplicates,
2327            );
2328            (e1, e2)
2329        };
2330
2331        if !duplicates.is_empty() {
2332            return Err(DuplicateItem::__internal_new(
2333                value,
2334                duplicates.iter().map(|ix| &self.items[*ix]).collect(),
2335            ));
2336        }
2337
2338        let next_index = self.items.assert_can_grow().insert(value);
2339        // e1 and e2 are all Some because if they were None, duplicates
2340        // would be non-empty, and we'd have bailed out earlier.
2341        e1.unwrap().insert(next_index);
2342        e2.unwrap().insert(next_index);
2343
2344        Ok(next_index)
2345    }
2346
2347    pub(super) fn remove_by_entry_index(
2348        &mut self,
2349        indexes: EntryIndexes,
2350    ) -> Vec<T> {
2351        let prepared = self.prepare_entry_index_removal(indexes);
2352        let mut old_items = Vec::with_capacity(prepared.len());
2353
2354        for duplicate in prepared {
2355            old_items.push(
2356                self.remove_duplicate(duplicate)
2357                    .expect("prepared duplicate index was present"),
2358            );
2359        }
2360
2361        old_items
2362    }
2363
2364    pub(super) fn remove_by_index(
2365        &mut self,
2366        remove_index: ItemIndex,
2367    ) -> Option<T> {
2368        // For panic safety, compute both key hashes and look up both table
2369        // entries while `self.items` still holds the value, then remove from
2370        // both tables and items in sequence. These lookups deliberately match
2371        // by `ItemIndex` rather than by user `Eq`: at this point we already
2372        // know which item is being removed, and user `Eq` might be
2373        // pathological. hashbrown's `find_entry_by_hash` is panic-safe because
2374        // the table is not mutated until `OccupiedEntry::remove` is called, so
2375        // a panic while hashing leaves items and both tables unmodified.
2376        // (Unlike the IdOrdMap path, no separate two-phase commit is needed:
2377        // the BTreeMap analog has to guard against a user-`Ord` panic during
2378        // the tree walk, but the hash walk here never invokes user code.)
2379        //
2380        // If either hash lookup misses — which happens when a `mem::forget`
2381        // on a `RefMut` bypassed the drop-time hash check and one of the
2382        // item's keys now hashes to a different bucket than its entry sits
2383        // in — fall back to a linear scan by `ItemIndex` for that table.
2384        // The fallback never invokes user `Hash`, so cleanup remains
2385        // panic-safe.
2386        let item = self.items.get(remove_index)?;
2387        let state = &self.tables.state;
2388        let hash1 = state.hash_one(item.key1());
2389        let hash2 = state.hash_one(item.key2());
2390        match self
2391            .tables
2392            .k1_to_item
2393            .find_entry_by_hash(hash1, |index| index == remove_index)
2394        {
2395            Ok(entry) => entry.remove(),
2396            Err(()) => self.tables.k1_to_item.remove_by_index(remove_index),
2397        }
2398        match self
2399            .tables
2400            .k2_to_item
2401            .find_entry_by_hash(hash2, |index| index == remove_index)
2402        {
2403            Ok(entry) => entry.remove(),
2404            Err(()) => self.tables.k2_to_item.remove_by_index(remove_index),
2405        }
2406        Some(
2407            self.items
2408                .remove(remove_index)
2409                .expect("items[remove_index] was Occupied above"),
2410        )
2411    }
2412
2413    /// Removes the item at `duplicate`, using already-computed key hashes when
2414    /// possible.
2415    ///
2416    /// The caller must ensure:
2417    ///
2418    /// * all user-controlled key extraction and hashing for the item at
2419    ///   `duplicate.index` has already completed;
2420    /// * the item at `duplicate.index` has not changed since those hashes were
2421    ///   computed;
2422    /// * removing this index from the item store and key tables preserves the
2423    ///   map/table invariants.
2424    ///
2425    /// The provided `duplicate.hashes` allow the normal commit path to remove
2426    /// key-table entries without recomputing user-controlled hashes. If a
2427    /// prehashed lookup misses, this falls back to removing by `ItemIndex`,
2428    /// which performs a linear scan over cached indexes and does not re-enter
2429    /// user code.
2430    fn remove_duplicate(&mut self, duplicate: PreparedDuplicate) -> Option<T> {
2431        let _ = self.items.get(duplicate.index)?;
2432
2433        let [hash1, hash2] = duplicate.hashes;
2434
2435        match self
2436            .tables
2437            .k1_to_item
2438            .find_entry_by_hash(hash1.hash(), |index| index == duplicate.index)
2439        {
2440            Ok(entry) => entry.remove(),
2441            Err(()) => self.tables.k1_to_item.remove_by_index(duplicate.index),
2442        }
2443
2444        match self
2445            .tables
2446            .k2_to_item
2447            .find_entry_by_hash(hash2.hash(), |index| index == duplicate.index)
2448        {
2449            Ok(entry) => entry.remove(),
2450            Err(()) => self.tables.k2_to_item.remove_by_index(duplicate.index),
2451        }
2452
2453        Some(
2454            self.items
2455                .remove(duplicate.index)
2456                .expect("items[duplicate.index] was Occupied above"),
2457        )
2458    }
2459
2460    pub(super) fn replace_at_indexes(
2461        &mut self,
2462        indexes: EntryIndexes,
2463        value: T,
2464    ) -> (ItemIndex, Vec<T>) {
2465        match indexes {
2466            EntryIndexes::Unique(index) => {
2467                {
2468                    let old_item = &self.items[index];
2469                    if old_item.key1() != value.key1() {
2470                        panic!("key1 mismatch");
2471                    }
2472                    if old_item.key2() != value.key2() {
2473                        panic!("key2 mismatch");
2474                    }
2475                }
2476
2477                let mut old_items = Vec::with_capacity(1);
2478                let old_item = self.items.replace(index, value);
2479                old_items.push(old_item);
2480
2481                (index, old_items)
2482            }
2483            EntryIndexes::NonUnique { index1, index2 } => {
2484                let prepared = self.prepare_insert_overwrite(&value);
2485
2486                if prepared.index1 != index1 {
2487                    panic!("key1 mismatch");
2488                }
2489                if prepared.index2 != index2 {
2490                    panic!("key2 mismatch");
2491                }
2492
2493                let mut old_items =
2494                    Vec::with_capacity(prepared.duplicate_count());
2495
2496                self.try_reserve_insert_overwrite_commit(
2497                    prepared.needs_new_item_slot(),
2498                )
2499                .expect("reserved item slot");
2500
2501                let next_index = self.commit_insert_overwrite(
2502                    value,
2503                    prepared,
2504                    &mut old_items,
2505                );
2506
2507                (next_index, old_items)
2508            }
2509        }
2510    }
2511}
2512
2513impl<'a, T, S, A> fmt::Debug for BiHashMap<T, S, A>
2514where
2515    T: BiHashItem + fmt::Debug,
2516    T::K1<'a>: fmt::Debug,
2517    T::K2<'a>: fmt::Debug,
2518    T: 'a,
2519    A: Allocator,
2520{
2521    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2522        let mut map = f.debug_map();
2523        for item in self.items.values() {
2524            let key: KeyMap<'_, T> =
2525                KeyMap { key1: item.key1(), key2: item.key2() };
2526
2527            // SAFETY:
2528            //
2529            // * Lifetime extension: for a type T and two lifetime params 'a and
2530            //   'b, T<'a> and T<'b> aren't guaranteed to have the same layout,
2531            //   but (a) that is true today and (b) it would be shocking and
2532            //   break half the Rust ecosystem if that were to change in the
2533            //   future.
2534            // * We only use key within the scope of this block before immediately
2535            //   dropping it. In particular, map.entry calls key.fmt() without
2536            //   holding a reference to it.
2537            let key: KeyMap<'a, T> = unsafe {
2538                core::mem::transmute::<KeyMap<'_, T>, KeyMap<'a, T>>(key)
2539            };
2540
2541            map.entry(&key as &dyn fmt::Debug, item);
2542        }
2543        map.finish()
2544    }
2545}
2546
2547struct KeyMap<'a, T: BiHashItem + 'a> {
2548    key1: T::K1<'a>,
2549    key2: T::K2<'a>,
2550}
2551
2552impl<'a, T: BiHashItem + 'a> fmt::Debug for KeyMap<'a, T>
2553where
2554    T::K1<'a>: fmt::Debug,
2555    T::K2<'a>: fmt::Debug,
2556{
2557    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2558        // We don't want to show key1 and key2 as a tuple since it's
2559        // misleading (suggests maps of tuples). The best we can do
2560        // instead is to show "{k1: "abc", k2: "xyz"}"
2561        f.debug_map()
2562            .entry(&StrDisplayAsDebug("k1"), &self.key1)
2563            .entry(&StrDisplayAsDebug("k2"), &self.key2)
2564            .finish()
2565    }
2566}
2567
2568/// The `PartialEq` implementation for `BiHashMap` checks that both maps have
2569/// the same items, regardless of insertion order.
2570///
2571/// # Examples
2572///
2573/// ```
2574/// # #[cfg(feature = "default-hasher")] {
2575/// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
2576///
2577/// #[derive(Debug, PartialEq, Eq)]
2578/// struct Item {
2579///     id: u32,
2580///     name: String,
2581///     value: i32,
2582/// }
2583///
2584/// impl BiHashItem for Item {
2585///     type K1<'a> = u32;
2586///     type K2<'a> = &'a str;
2587///
2588///     fn key1(&self) -> Self::K1<'_> {
2589///         self.id
2590///     }
2591///     fn key2(&self) -> Self::K2<'_> {
2592///         &self.name
2593///     }
2594///     bi_upcast!();
2595/// }
2596///
2597/// let mut map1 = BiHashMap::new();
2598/// map1.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
2599///     .unwrap();
2600/// map1.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
2601///     .unwrap();
2602///
2603/// let mut map2 = BiHashMap::new();
2604/// map2.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
2605///     .unwrap();
2606/// map2.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
2607///     .unwrap();
2608///
2609/// // Maps are equal even if items were inserted in different order
2610/// assert_eq!(map1, map2);
2611///
2612/// map2.insert_unique(Item { id: 3, name: "baz".to_string(), value: 200 })
2613///     .unwrap();
2614/// assert_ne!(map1, map2);
2615/// # }
2616/// ```
2617impl<T: BiHashItem + PartialEq, S: Clone + BuildHasher, A: Allocator> PartialEq
2618    for BiHashMap<T, S, A>
2619{
2620    fn eq(&self, other: &Self) -> bool {
2621        // Implementing PartialEq for BiHashMap is tricky because BiHashMap is
2622        // not semantically like an IndexMap: two maps are equivalent even if
2623        // their items are in a different order. In other words, any permutation
2624        // of items is equivalent.
2625        //
2626        // We also can't sort the items because they're not necessarily Ord.
2627        //
2628        // So we write a custom equality check that checks that each key in one
2629        // map points to the same item as in the other map.
2630
2631        if self.items.len() != other.items.len() {
2632            return false;
2633        }
2634
2635        // Walk over all the items in the first map and check that they point to
2636        // the same item in the second map.
2637        for item in self.items.values() {
2638            let k1 = item.key1();
2639            let k2 = item.key2();
2640
2641            // Check that the indexes are the same in the other map.
2642            let Some(other_ix1) = other.find1_index(&k1) else {
2643                return false;
2644            };
2645            let Some(other_ix2) = other.find2_index(&k2) else {
2646                return false;
2647            };
2648
2649            if other_ix1 != other_ix2 {
2650                // All the keys were present but they didn't point to the same
2651                // item.
2652                return false;
2653            }
2654
2655            // Check that the other map's item is the same as this map's
2656            // item. (This is what we use the `PartialEq` bound on T for.)
2657            //
2658            // Because we've checked that other_ix1 and other_ix2 are
2659            // Some, we know that it is valid and points to the expected item.
2660            let other_item = &other.items[other_ix1];
2661            if item != other_item {
2662                return false;
2663            }
2664        }
2665
2666        true
2667    }
2668}
2669
2670// The Eq bound on T ensures that the BiHashMap forms an equivalence class.
2671impl<T: BiHashItem + Eq, S: Clone + BuildHasher, A: Allocator> Eq
2672    for BiHashMap<T, S, A>
2673{
2674}
2675
2676fn detect_dup_or_insert<'a, A: Allocator>(
2677    item: hash_table::Entry<'a, A>,
2678    duplicates: &mut BTreeSet<ItemIndex>,
2679) -> Option<hash_table::VacantEntry<'a, A>> {
2680    match item {
2681        hash_table::Entry::Vacant(slot) => Some(slot),
2682        hash_table::Entry::Occupied(slot) => {
2683            duplicates.insert(slot.get());
2684            None
2685        }
2686    }
2687}
2688
2689/// The `Extend` implementation overwrites duplicates. In the future, there will
2690/// also be an `extend_unique` method that will return an error.
2691///
2692/// # Examples
2693///
2694/// ```
2695/// # #[cfg(feature = "default-hasher")] {
2696/// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
2697///
2698/// #[derive(Debug, PartialEq, Eq)]
2699/// struct Item {
2700///     id: u32,
2701///     name: String,
2702///     value: i32,
2703/// }
2704///
2705/// impl BiHashItem for Item {
2706///     type K1<'a> = u32;
2707///     type K2<'a> = &'a str;
2708///
2709///     fn key1(&self) -> Self::K1<'_> {
2710///         self.id
2711///     }
2712///     fn key2(&self) -> Self::K2<'_> {
2713///         &self.name
2714///     }
2715///     bi_upcast!();
2716/// }
2717///
2718/// let mut map = BiHashMap::new();
2719/// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 }).unwrap();
2720///
2721/// let new_items = vec![
2722///     Item { id: 2, name: "bar".to_string(), value: 99 },
2723///     Item { id: 1, name: "baz".to_string(), value: 100 }, // overwrites existing
2724/// ];
2725///
2726/// map.extend(new_items);
2727/// assert_eq!(map.len(), 2);
2728/// assert_eq!(map.get1(&1).unwrap().name, "baz"); // overwritten
2729/// assert_eq!(map.get1(&1).unwrap().value, 100);
2730/// # }
2731/// ```
2732impl<T: BiHashItem, S: Clone + BuildHasher, A: Allocator> Extend<T>
2733    for BiHashMap<T, S, A>
2734{
2735    fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
2736        // Keys may already be present in the map, or multiple times in the
2737        // iterator. Reserve the entire hint lower bound if the map is empty.
2738        // Otherwise reserve half the hint (rounded up), so the map will only
2739        // resize twice in the worst case.
2740        let iter = iter.into_iter();
2741        let reserve = if self.is_empty() {
2742            iter.size_hint().0
2743        } else {
2744            iter.size_hint().0.div_ceil(2)
2745        };
2746        self.reserve(reserve);
2747        for item in iter {
2748            self.insert_overwrite(item);
2749        }
2750    }
2751}
2752
2753impl<'a, T: BiHashItem, S: Clone + BuildHasher, A: Allocator> IntoIterator
2754    for &'a BiHashMap<T, S, A>
2755{
2756    type Item = &'a T;
2757    type IntoIter = Iter<'a, T>;
2758
2759    #[inline]
2760    fn into_iter(self) -> Self::IntoIter {
2761        self.iter()
2762    }
2763}
2764
2765impl<'a, T: BiHashItem, S: Clone + BuildHasher, A: Allocator> IntoIterator
2766    for &'a mut BiHashMap<T, S, A>
2767{
2768    type Item = RefMut<'a, T, S>;
2769    type IntoIter = IterMut<'a, T, S, A>;
2770
2771    #[inline]
2772    fn into_iter(self) -> Self::IntoIter {
2773        self.iter_mut()
2774    }
2775}
2776
2777impl<T: BiHashItem, S: Clone + BuildHasher, A: Allocator> IntoIterator
2778    for BiHashMap<T, S, A>
2779{
2780    type Item = T;
2781    type IntoIter = IntoIter<T, A>;
2782
2783    #[inline]
2784    fn into_iter(self) -> Self::IntoIter {
2785        IntoIter::new(self.items)
2786    }
2787}
2788
2789/// The `FromIterator` implementation for `BiHashMap` overwrites duplicate
2790/// items.
2791///
2792/// # Examples
2793///
2794/// ```
2795/// # #[cfg(feature = "default-hasher")] {
2796/// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
2797///
2798/// #[derive(Debug, PartialEq, Eq)]
2799/// struct Item {
2800///     id: u32,
2801///     name: String,
2802///     value: i32,
2803/// }
2804///
2805/// impl BiHashItem for Item {
2806///     type K1<'a> = u32;
2807///     type K2<'a> = &'a str;
2808///
2809///     fn key1(&self) -> Self::K1<'_> {
2810///         self.id
2811///     }
2812///     fn key2(&self) -> Self::K2<'_> {
2813///         &self.name
2814///     }
2815///     bi_upcast!();
2816/// }
2817///
2818/// let items = vec![
2819///     Item { id: 1, name: "foo".to_string(), value: 42 },
2820///     Item { id: 2, name: "bar".to_string(), value: 99 },
2821///     Item { id: 1, name: "baz".to_string(), value: 100 }, // overwrites first item
2822/// ];
2823///
2824/// let map: BiHashMap<Item> = items.into_iter().collect();
2825/// assert_eq!(map.len(), 2);
2826/// assert_eq!(map.get1(&1).unwrap().name, "baz"); // overwritten
2827/// assert_eq!(map.get1(&1).unwrap().value, 100);
2828/// assert_eq!(map.get1(&2).unwrap().value, 99);
2829/// # }
2830/// ```
2831impl<T: BiHashItem, S: Clone + BuildHasher + Default, A: Default + Allocator>
2832    FromIterator<T> for BiHashMap<T, S, A>
2833{
2834    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
2835        let mut map = BiHashMap::default();
2836        map.extend(iter);
2837        map
2838    }
2839}