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.items.validate(compactness)?;
1106        self.tables.validate(self.len(), compactness)?;
1107
1108        // Check that the indexes are all correct.
1109        for (ix, item) in self.items.iter() {
1110            let key1 = item.key1();
1111            let key2 = item.key2();
1112
1113            let Some(ix1) = self.find1_index(&key1) else {
1114                return Err(ValidationError::general(format!(
1115                    "item at index {ix} has no key1 index"
1116                )));
1117            };
1118            let Some(ix2) = self.find2_index(&key2) else {
1119                return Err(ValidationError::general(format!(
1120                    "item at index {ix} has no key2 index"
1121                )));
1122            };
1123
1124            if ix1 != ix || ix2 != ix {
1125                return Err(ValidationError::general(format!(
1126                    "item at index {ix} has inconsistent indexes: {ix1}/{ix2}"
1127                )));
1128            }
1129        }
1130
1131        Ok(())
1132    }
1133
1134    /// Inserts a value into the map, removing any conflicting items and
1135    /// returning a list of those items.
1136    ///
1137    /// # Examples
1138    ///
1139    /// ```
1140    /// # #[cfg(feature = "default-hasher")] {
1141    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
1142    ///
1143    /// #[derive(Debug, PartialEq, Eq)]
1144    /// struct Item {
1145    ///     id: u32,
1146    ///     name: String,
1147    ///     value: i32,
1148    /// }
1149    ///
1150    /// impl BiHashItem for Item {
1151    ///     type K1<'a> = u32;
1152    ///     type K2<'a> = &'a str;
1153    ///
1154    ///     fn key1(&self) -> Self::K1<'_> {
1155    ///         self.id
1156    ///     }
1157    ///     fn key2(&self) -> Self::K2<'_> {
1158    ///         &self.name
1159    ///     }
1160    ///     bi_upcast!();
1161    /// }
1162    ///
1163    /// let mut map = BiHashMap::new();
1164    /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
1165    ///     .unwrap();
1166    /// map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
1167    ///     .unwrap();
1168    ///
1169    /// // Insert an item with conflicting key1
1170    /// let removed = map.insert_overwrite(Item {
1171    ///     id: 1,
1172    ///     name: "baz".to_string(),
1173    ///     value: 100,
1174    /// });
1175    /// assert_eq!(removed.len(), 1);
1176    /// assert_eq!(removed[0].name, "foo");
1177    /// assert_eq!(removed[0].value, 42);
1178    ///
1179    /// assert_eq!(map.len(), 2);
1180    /// assert_eq!(map.get1(&1).unwrap().name, "baz");
1181    /// # }
1182    /// ```
1183    #[doc(alias = "insert")]
1184    pub fn insert_overwrite(&mut self, value: T) -> Vec<T> {
1185        let prepared = self.prepare_insert_overwrite(&value);
1186
1187        let mut duplicates = Vec::with_capacity(prepared.duplicate_count());
1188
1189        self.try_reserve_insert_overwrite_commit(
1190            prepared.needs_new_item_slot(),
1191        )
1192        .expect("reserved space successfully");
1193
1194        self.commit_insert_overwrite(value, prepared, &mut duplicates);
1195
1196        duplicates
1197    }
1198
1199    /// Inserts a value into the set, returning an error if any duplicates were
1200    /// added.
1201    ///
1202    /// # Examples
1203    ///
1204    /// ```
1205    /// # #[cfg(feature = "default-hasher")] {
1206    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
1207    ///
1208    /// #[derive(Debug, PartialEq, Eq)]
1209    /// struct Item {
1210    ///     id: u32,
1211    ///     name: String,
1212    ///     value: i32,
1213    /// }
1214    ///
1215    /// impl BiHashItem for Item {
1216    ///     type K1<'a> = u32;
1217    ///     type K2<'a> = &'a str;
1218    ///
1219    ///     fn key1(&self) -> Self::K1<'_> {
1220    ///         self.id
1221    ///     }
1222    ///     fn key2(&self) -> Self::K2<'_> {
1223    ///         &self.name
1224    ///     }
1225    ///     bi_upcast!();
1226    /// }
1227    ///
1228    /// let mut map = BiHashMap::new();
1229    ///
1230    /// // Successful insertion
1231    /// assert!(
1232    ///     map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
1233    ///         .is_ok()
1234    /// );
1235    /// assert!(
1236    ///     map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
1237    ///         .is_ok()
1238    /// );
1239    ///
1240    /// // Duplicate key1
1241    /// assert!(
1242    ///     map.insert_unique(Item { id: 1, name: "baz".to_string(), value: 100 })
1243    ///         .is_err()
1244    /// );
1245    ///
1246    /// // Duplicate key2
1247    /// assert!(
1248    ///     map.insert_unique(Item { id: 3, name: "foo".to_string(), value: 200 })
1249    ///         .is_err()
1250    /// );
1251    /// # }
1252    /// ```
1253    pub fn insert_unique(
1254        &mut self,
1255        value: T,
1256    ) -> Result<(), DuplicateItem<T, &T>> {
1257        let _ = self.insert_unique_impl(value)?;
1258        Ok(())
1259    }
1260
1261    /// Returns true if the map contains a single item that matches both `key1` and `key2`.
1262    ///
1263    /// # Examples
1264    ///
1265    /// ```
1266    /// # #[cfg(feature = "default-hasher")] {
1267    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
1268    ///
1269    /// #[derive(Debug, PartialEq, Eq)]
1270    /// struct Item {
1271    ///     id: u32,
1272    ///     name: String,
1273    ///     value: i32,
1274    /// }
1275    ///
1276    /// impl BiHashItem for Item {
1277    ///     type K1<'a> = u32;
1278    ///     type K2<'a> = &'a str;
1279    ///
1280    ///     fn key1(&self) -> Self::K1<'_> {
1281    ///         self.id
1282    ///     }
1283    ///     fn key2(&self) -> Self::K2<'_> {
1284    ///         &self.name
1285    ///     }
1286    ///     bi_upcast!();
1287    /// }
1288    ///
1289    /// let mut map = BiHashMap::new();
1290    /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 }).unwrap();
1291    /// map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 }).unwrap();
1292    ///
1293    /// assert!(map.contains_key_unique(&1, &"foo"));
1294    /// assert!(map.contains_key_unique(&2, &"bar"));
1295    /// assert!(!map.contains_key_unique(&1, &"bar")); // key1 exists but key2 doesn't match
1296    /// assert!(!map.contains_key_unique(&3, &"baz")); // neither key exists
1297    /// # }
1298    /// ```
1299    pub fn contains_key_unique<'a, Q1, Q2>(
1300        &'a self,
1301        key1: &Q1,
1302        key2: &Q2,
1303    ) -> bool
1304    where
1305        Q1: Hash + Equivalent<T::K1<'a>> + ?Sized,
1306        Q2: Hash + Equivalent<T::K2<'a>> + ?Sized,
1307    {
1308        self.get_unique(key1, key2).is_some()
1309    }
1310
1311    /// Gets a reference to the unique item associated with the given `key1` and
1312    /// `key2`, if it exists.
1313    ///
1314    /// # Examples
1315    ///
1316    /// ```
1317    /// # #[cfg(feature = "default-hasher")] {
1318    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
1319    ///
1320    /// #[derive(Debug, PartialEq, Eq)]
1321    /// struct Item {
1322    ///     id: u32,
1323    ///     name: String,
1324    ///     value: i32,
1325    /// }
1326    ///
1327    /// impl BiHashItem for Item {
1328    ///     type K1<'a> = u32;
1329    ///     type K2<'a> = &'a str;
1330    ///
1331    ///     fn key1(&self) -> Self::K1<'_> {
1332    ///         self.id
1333    ///     }
1334    ///     fn key2(&self) -> Self::K2<'_> {
1335    ///         &self.name
1336    ///     }
1337    ///     bi_upcast!();
1338    /// }
1339    ///
1340    /// let mut map = BiHashMap::new();
1341    /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 }).unwrap();
1342    /// map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 }).unwrap();
1343    ///
1344    /// assert_eq!(map.get_unique(&1, &"foo").unwrap().value, 42);
1345    /// assert_eq!(map.get_unique(&2, &"bar").unwrap().value, 99);
1346    /// assert!(map.get_unique(&1, &"bar").is_none()); // key1 exists but key2 doesn't match
1347    /// assert!(map.get_unique(&3, &"baz").is_none()); // neither key exists
1348    /// # }
1349    /// ```
1350    pub fn get_unique<'a, Q1, Q2>(
1351        &'a self,
1352        key1: &Q1,
1353        key2: &Q2,
1354    ) -> Option<&'a T>
1355    where
1356        Q1: Hash + Equivalent<T::K1<'a>> + ?Sized,
1357        Q2: Hash + Equivalent<T::K2<'a>> + ?Sized,
1358    {
1359        let index = self.find1_index(key1)?;
1360        let item = &self.items[index];
1361        if key2.equivalent(&item.key2()) { Some(item) } else { None }
1362    }
1363
1364    /// Gets a mutable reference to the unique item associated with the given
1365    /// `key1` and `key2`, if it exists.
1366    pub fn get_mut_unique<'a, Q1, Q2>(
1367        &'a mut self,
1368        key1: &Q1,
1369        key2: &Q2,
1370    ) -> Option<RefMut<'a, T, S>>
1371    where
1372        Q1: Hash + Equivalent<T::K1<'a>> + ?Sized,
1373        Q2: Hash + Equivalent<T::K2<'a>> + ?Sized,
1374    {
1375        let (dormant_map, index) = {
1376            let (map, dormant_map) = DormantMutRef::new(self);
1377            let index = map.find1_index(key1)?;
1378            // Check key2 match before proceeding
1379            if !key2.equivalent(&map.items[index].key2()) {
1380                return None;
1381            }
1382            (dormant_map, index)
1383        };
1384
1385        // SAFETY: `map` is not used after this point.
1386        let awakened_map = unsafe { dormant_map.awaken() };
1387        let item = &mut awakened_map.items[index];
1388        let state = awakened_map.tables.state.clone();
1389        let hashes =
1390            awakened_map.tables.make_hashes::<T>(&item.key1(), &item.key2());
1391        Some(RefMut::new(state, hashes, item))
1392    }
1393
1394    /// Removes the item uniquely identified by `key1` and `key2`, if it exists.
1395    pub fn remove_unique<'a, Q1, Q2>(
1396        &'a mut self,
1397        key1: &Q1,
1398        key2: &Q2,
1399    ) -> Option<T>
1400    where
1401        Q1: Hash + Equivalent<T::K1<'a>> + ?Sized,
1402        Q2: Hash + Equivalent<T::K2<'a>> + ?Sized,
1403    {
1404        let (dormant_map, remove_index) = {
1405            let (map, dormant_map) = DormantMutRef::new(self);
1406            let remove_index = map.find1_index(key1)?;
1407            if !key2.equivalent(&map.items[remove_index].key2()) {
1408                return None;
1409            }
1410            (dormant_map, remove_index)
1411        };
1412
1413        // SAFETY: `map` is not used after this point.
1414        let awakened_map = unsafe { dormant_map.awaken() };
1415
1416        awakened_map.remove_by_index(remove_index)
1417    }
1418
1419    /// Returns true if the map contains the given `key1`.
1420    ///
1421    /// # Examples
1422    ///
1423    /// ```
1424    /// # #[cfg(feature = "default-hasher")] {
1425    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
1426    ///
1427    /// #[derive(Debug, PartialEq, Eq)]
1428    /// struct Item {
1429    ///     id: u32,
1430    ///     name: String,
1431    ///     value: i32,
1432    /// }
1433    ///
1434    /// impl BiHashItem for Item {
1435    ///     type K1<'a> = u32;
1436    ///     type K2<'a> = &'a str;
1437    ///
1438    ///     fn key1(&self) -> Self::K1<'_> {
1439    ///         self.id
1440    ///     }
1441    ///     fn key2(&self) -> Self::K2<'_> {
1442    ///         &self.name
1443    ///     }
1444    ///     bi_upcast!();
1445    /// }
1446    ///
1447    /// let mut map = BiHashMap::new();
1448    /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
1449    ///     .unwrap();
1450    /// map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
1451    ///     .unwrap();
1452    ///
1453    /// assert!(map.contains_key1(&1));
1454    /// assert!(map.contains_key1(&2));
1455    /// assert!(!map.contains_key1(&3));
1456    /// # }
1457    /// ```
1458    pub fn contains_key1<'a, Q>(&'a self, key1: &Q) -> bool
1459    where
1460        Q: Hash + Equivalent<T::K1<'a>> + ?Sized,
1461    {
1462        self.find1_index(key1).is_some()
1463    }
1464
1465    /// Gets a reference to the value associated with the given `key1`.
1466    ///
1467    /// # Examples
1468    ///
1469    /// ```
1470    /// # #[cfg(feature = "default-hasher")] {
1471    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
1472    ///
1473    /// #[derive(Debug, PartialEq, Eq)]
1474    /// struct Item {
1475    ///     id: u32,
1476    ///     name: String,
1477    ///     value: i32,
1478    /// }
1479    ///
1480    /// impl BiHashItem for Item {
1481    ///     type K1<'a> = u32;
1482    ///     type K2<'a> = &'a str;
1483    ///
1484    ///     fn key1(&self) -> Self::K1<'_> {
1485    ///         self.id
1486    ///     }
1487    ///     fn key2(&self) -> Self::K2<'_> {
1488    ///         &self.name
1489    ///     }
1490    ///     bi_upcast!();
1491    /// }
1492    ///
1493    /// let mut map = BiHashMap::new();
1494    /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
1495    ///     .unwrap();
1496    /// map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
1497    ///     .unwrap();
1498    ///
1499    /// assert_eq!(map.get1(&1).unwrap().value, 42);
1500    /// assert_eq!(map.get1(&2).unwrap().value, 99);
1501    /// assert!(map.get1(&3).is_none());
1502    /// # }
1503    /// ```
1504    pub fn get1<'a, Q>(&'a self, key1: &Q) -> Option<&'a T>
1505    where
1506        Q: Hash + Equivalent<T::K1<'a>> + ?Sized,
1507    {
1508        self.find1(key1)
1509    }
1510
1511    /// Gets a mutable reference to the value associated with the given `key1`.
1512    pub fn get1_mut<'a, Q>(&'a mut self, key1: &Q) -> Option<RefMut<'a, T, S>>
1513    where
1514        Q: Hash + Equivalent<T::K1<'a>> + ?Sized,
1515    {
1516        let (dormant_map, index) = {
1517            let (map, dormant_map) = DormantMutRef::new(self);
1518            let index = map.find1_index(key1)?;
1519            (dormant_map, index)
1520        };
1521
1522        // SAFETY: `map` is not used after this point.
1523        let awakened_map = unsafe { dormant_map.awaken() };
1524        let item = &mut awakened_map.items[index];
1525        let state = awakened_map.tables.state.clone();
1526        let hashes =
1527            awakened_map.tables.make_hashes::<T>(&item.key1(), &item.key2());
1528        Some(RefMut::new(state, hashes, item))
1529    }
1530
1531    /// Removes an item from the map by its `key1`.
1532    ///
1533    /// # Examples
1534    ///
1535    /// ```
1536    /// # #[cfg(feature = "default-hasher")] {
1537    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
1538    ///
1539    /// #[derive(Debug, PartialEq, Eq)]
1540    /// struct Item {
1541    ///     id: u32,
1542    ///     name: String,
1543    ///     value: i32,
1544    /// }
1545    ///
1546    /// impl BiHashItem for Item {
1547    ///     type K1<'a> = u32;
1548    ///     type K2<'a> = &'a str;
1549    ///
1550    ///     fn key1(&self) -> Self::K1<'_> {
1551    ///         self.id
1552    ///     }
1553    ///     fn key2(&self) -> Self::K2<'_> {
1554    ///         &self.name
1555    ///     }
1556    ///     bi_upcast!();
1557    /// }
1558    ///
1559    /// let mut map = BiHashMap::new();
1560    /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
1561    ///     .unwrap();
1562    /// map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
1563    ///     .unwrap();
1564    ///
1565    /// let removed = map.remove1(&1);
1566    /// assert_eq!(removed.unwrap().value, 42);
1567    /// assert_eq!(map.len(), 1);
1568    /// assert!(map.get1(&1).is_none());
1569    /// assert!(map.remove1(&3).is_none());
1570    /// # }
1571    /// ```
1572    pub fn remove1<'a, Q>(&'a mut self, key1: &Q) -> Option<T>
1573    where
1574        Q: Hash + Equivalent<T::K1<'a>> + ?Sized,
1575    {
1576        let (dormant_map, remove_index) = {
1577            let (map, dormant_map) = DormantMutRef::new(self);
1578            let remove_index = map.find1_index(key1)?;
1579            (dormant_map, remove_index)
1580        };
1581
1582        // SAFETY: `map` is not used after this point.
1583        let awakened_map = unsafe { dormant_map.awaken() };
1584
1585        awakened_map.remove_by_index(remove_index)
1586    }
1587
1588    /// Returns true if the map contains the given `key2`.
1589    ///
1590    /// # Examples
1591    ///
1592    /// ```
1593    /// # #[cfg(feature = "default-hasher")] {
1594    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
1595    ///
1596    /// #[derive(Debug, PartialEq, Eq)]
1597    /// struct Item {
1598    ///     id: u32,
1599    ///     name: String,
1600    ///     value: i32,
1601    /// }
1602    ///
1603    /// impl BiHashItem for Item {
1604    ///     type K1<'a> = u32;
1605    ///     type K2<'a> = &'a str;
1606    ///
1607    ///     fn key1(&self) -> Self::K1<'_> {
1608    ///         self.id
1609    ///     }
1610    ///     fn key2(&self) -> Self::K2<'_> {
1611    ///         &self.name
1612    ///     }
1613    ///     bi_upcast!();
1614    /// }
1615    ///
1616    /// let mut map = BiHashMap::new();
1617    /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
1618    ///     .unwrap();
1619    /// map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
1620    ///     .unwrap();
1621    ///
1622    /// assert!(map.contains_key2(&"foo"));
1623    /// assert!(map.contains_key2(&"bar"));
1624    /// assert!(!map.contains_key2(&"baz"));
1625    /// # }
1626    /// ```
1627    pub fn contains_key2<'a, Q>(&'a self, key2: &Q) -> bool
1628    where
1629        Q: Hash + Equivalent<T::K2<'a>> + ?Sized,
1630    {
1631        self.find2_index(key2).is_some()
1632    }
1633
1634    /// Gets a reference to the value associated with the given `key2`.
1635    ///
1636    /// # Examples
1637    ///
1638    /// ```
1639    /// # #[cfg(feature = "default-hasher")] {
1640    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
1641    ///
1642    /// #[derive(Debug, PartialEq, Eq)]
1643    /// struct Item {
1644    ///     id: u32,
1645    ///     name: String,
1646    ///     value: i32,
1647    /// }
1648    ///
1649    /// impl BiHashItem for Item {
1650    ///     type K1<'a> = u32;
1651    ///     type K2<'a> = &'a str;
1652    ///
1653    ///     fn key1(&self) -> Self::K1<'_> {
1654    ///         self.id
1655    ///     }
1656    ///     fn key2(&self) -> Self::K2<'_> {
1657    ///         &self.name
1658    ///     }
1659    ///     bi_upcast!();
1660    /// }
1661    ///
1662    /// let mut map = BiHashMap::new();
1663    /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
1664    ///     .unwrap();
1665    /// map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
1666    ///     .unwrap();
1667    ///
1668    /// assert_eq!(map.get2(&"foo").unwrap().value, 42);
1669    /// assert_eq!(map.get2(&"bar").unwrap().value, 99);
1670    /// assert!(map.get2(&"baz").is_none());
1671    /// # }
1672    /// ```
1673    pub fn get2<'a, Q>(&'a self, key2: &Q) -> Option<&'a T>
1674    where
1675        Q: Hash + Equivalent<T::K2<'a>> + ?Sized,
1676    {
1677        self.find2(key2)
1678    }
1679
1680    /// Gets a mutable reference to the value associated with the given `key2`.
1681    ///
1682    /// # Examples
1683    ///
1684    /// ```
1685    /// # #[cfg(feature = "default-hasher")] {
1686    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
1687    ///
1688    /// #[derive(Debug, PartialEq, Eq)]
1689    /// struct Item {
1690    ///     id: u32,
1691    ///     name: String,
1692    ///     value: i32,
1693    /// }
1694    ///
1695    /// impl BiHashItem for Item {
1696    ///     type K1<'a> = u32;
1697    ///     type K2<'a> = &'a str;
1698    ///
1699    ///     fn key1(&self) -> Self::K1<'_> {
1700    ///         self.id
1701    ///     }
1702    ///     fn key2(&self) -> Self::K2<'_> {
1703    ///         &self.name
1704    ///     }
1705    ///     bi_upcast!();
1706    /// }
1707    ///
1708    /// let mut map = BiHashMap::new();
1709    /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
1710    ///     .unwrap();
1711    ///
1712    /// if let Some(mut item_ref) = map.get2_mut(&"foo") {
1713    ///     item_ref.value = 100;
1714    /// }
1715    ///
1716    /// assert_eq!(map.get2(&"foo").unwrap().value, 100);
1717    /// # }
1718    /// ```
1719    pub fn get2_mut<'a, Q>(&'a mut self, key2: &Q) -> Option<RefMut<'a, T, S>>
1720    where
1721        Q: Hash + Equivalent<T::K2<'a>> + ?Sized,
1722    {
1723        let (dormant_map, index) = {
1724            let (map, dormant_map) = DormantMutRef::new(self);
1725            let index = map.find2_index(key2)?;
1726            (dormant_map, index)
1727        };
1728
1729        // SAFETY: `map` is not used after this point.
1730        let awakened_map = unsafe { dormant_map.awaken() };
1731        let item = &mut awakened_map.items[index];
1732        let state = awakened_map.tables.state.clone();
1733        let hashes =
1734            awakened_map.tables.make_hashes::<T>(&item.key1(), &item.key2());
1735        Some(RefMut::new(state, hashes, item))
1736    }
1737
1738    /// Removes an item from the map by its `key2`.
1739    ///
1740    /// # Examples
1741    ///
1742    /// ```
1743    /// # #[cfg(feature = "default-hasher")] {
1744    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
1745    ///
1746    /// #[derive(Debug, PartialEq, Eq)]
1747    /// struct Item {
1748    ///     id: u32,
1749    ///     name: String,
1750    ///     value: i32,
1751    /// }
1752    ///
1753    /// impl BiHashItem for Item {
1754    ///     type K1<'a> = u32;
1755    ///     type K2<'a> = &'a str;
1756    ///
1757    ///     fn key1(&self) -> Self::K1<'_> {
1758    ///         self.id
1759    ///     }
1760    ///     fn key2(&self) -> Self::K2<'_> {
1761    ///         &self.name
1762    ///     }
1763    ///     bi_upcast!();
1764    /// }
1765    ///
1766    /// let mut map = BiHashMap::new();
1767    /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
1768    ///     .unwrap();
1769    /// map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
1770    ///     .unwrap();
1771    ///
1772    /// let removed = map.remove2(&"foo");
1773    /// assert_eq!(removed.unwrap().value, 42);
1774    /// assert_eq!(map.len(), 1);
1775    /// assert!(map.get2(&"foo").is_none());
1776    /// assert!(map.remove2(&"baz").is_none());
1777    /// # }
1778    /// ```
1779    pub fn remove2<'a, Q>(&'a mut self, key2: &Q) -> Option<T>
1780    where
1781        Q: Hash + Equivalent<T::K2<'a>> + ?Sized,
1782    {
1783        let (dormant_map, remove_index) = {
1784            let (map, dormant_map) = DormantMutRef::new(self);
1785            let remove_index = map.find2_index(key2)?;
1786            (dormant_map, remove_index)
1787        };
1788
1789        // SAFETY: `map` is not used after this point.
1790        let awakened_map = unsafe { dormant_map.awaken() };
1791
1792        awakened_map.remove_by_index(remove_index)
1793    }
1794
1795    /// Retrieves an entry by its keys.
1796    ///
1797    /// Due to borrow checker limitations, this always accepts owned keys rather
1798    /// than a borrowed form of them.
1799    ///
1800    /// # Examples
1801    ///
1802    /// ```
1803    /// # #[cfg(feature = "default-hasher")] {
1804    /// use iddqd::{BiHashItem, BiHashMap, bi_hash_map, bi_upcast};
1805    ///
1806    /// #[derive(Debug, PartialEq, Eq)]
1807    /// struct Item {
1808    ///     id: u32,
1809    ///     name: String,
1810    ///     value: i32,
1811    /// }
1812    ///
1813    /// impl BiHashItem for Item {
1814    ///     type K1<'a> = u32;
1815    ///     type K2<'a> = &'a str;
1816    ///
1817    ///     fn key1(&self) -> Self::K1<'_> {
1818    ///         self.id
1819    ///     }
1820    ///     fn key2(&self) -> Self::K2<'_> {
1821    ///         &self.name
1822    ///     }
1823    ///     bi_upcast!();
1824    /// }
1825    ///
1826    /// let mut map = BiHashMap::new();
1827    /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
1828    ///     .unwrap();
1829    ///
1830    /// // Get existing entry
1831    /// match map.entry(1, "foo") {
1832    ///     bi_hash_map::Entry::Occupied(entry) => {
1833    ///         assert_eq!(entry.get().as_unique().unwrap().value, 42);
1834    ///     }
1835    ///     bi_hash_map::Entry::Vacant(_) => panic!("Should be occupied"),
1836    /// }
1837    ///
1838    /// // Try to get a non-existing entry
1839    /// match map.entry(2, "bar") {
1840    ///     bi_hash_map::Entry::Occupied(_) => panic!("Should be vacant"),
1841    ///     bi_hash_map::Entry::Vacant(entry) => {
1842    ///         entry.insert(Item { id: 2, name: "bar".to_string(), value: 99 });
1843    ///     }
1844    /// }
1845    ///
1846    /// assert_eq!(map.len(), 2);
1847    /// # }
1848    /// ```
1849    pub fn entry<'a>(
1850        &'a mut self,
1851        key1: T::K1<'_>,
1852        key2: T::K2<'_>,
1853    ) -> Entry<'a, T, S, A> {
1854        // Why does this always take owned keys? Well, it would seem like we
1855        // should be able to pass in any Q1 and Q2 that are equivalent. That
1856        // results in *this* code compiling fine, but callers have trouble using
1857        // it because the borrow checker believes the keys are borrowed for the
1858        // full 'a rather than a shorter lifetime.
1859        //
1860        // By accepting owned keys, we can use the upcast functions to convert
1861        // them to a shorter lifetime (so this function accepts T::K1<'_> rather
1862        // than T::K1<'a>).
1863        //
1864        // Really, the solution here is to allow GATs to require covariant
1865        // parameters. If that were allowed, the borrow checker should be able
1866        // to figure out that keys don't need to be borrowed for the full 'a,
1867        // just for some shorter lifetime.
1868        let (map, dormant_map) = DormantMutRef::new(self);
1869        let key1 = T::upcast_key1(key1);
1870        let key2 = T::upcast_key2(key2);
1871        let (index1, index2) = {
1872            // index1 and index2 are explicitly typed to show that it has a
1873            // trivial Drop impl that doesn't capture anything from map.
1874            let index1: Option<ItemIndex> = map.tables.k1_to_item.find_index(
1875                &map.tables.state,
1876                &key1,
1877                |index| map.items[index].key1(),
1878            );
1879            let index2: Option<ItemIndex> = map.tables.k2_to_item.find_index(
1880                &map.tables.state,
1881                &key2,
1882                |index| map.items[index].key2(),
1883            );
1884            (index1, index2)
1885        };
1886
1887        match (index1, index2) {
1888            (Some(index1), Some(index2)) if index1 == index2 => {
1889                // The item is already in the map.
1890                drop(key1);
1891                Entry::Occupied(
1892                    // SAFETY: `map` is not used after this point.
1893                    unsafe {
1894                        OccupiedEntry::new(
1895                            dormant_map,
1896                            EntryIndexes::Unique(index1),
1897                        )
1898                    },
1899                )
1900            }
1901            (None, None) => {
1902                let hashes = map.tables.make_hashes::<T>(&key1, &key2);
1903                Entry::Vacant(
1904                    // SAFETY: `map` is not used after this point.
1905                    unsafe { VacantEntry::new(dormant_map, hashes) },
1906                )
1907            }
1908            (index1, index2) => Entry::Occupied(
1909                // SAFETY: `map` is not used after this point.
1910                unsafe {
1911                    OccupiedEntry::new(
1912                        dormant_map,
1913                        EntryIndexes::NonUnique { index1, index2 },
1914                    )
1915                },
1916            ),
1917        }
1918    }
1919
1920    /// Retains only the elements specified by the predicate.
1921    ///
1922    /// In other words, remove all items `T` for which `f(RefMut<T>)` returns
1923    /// false. The elements are visited in an arbitrary order.
1924    ///
1925    /// # Examples
1926    ///
1927    /// ```
1928    /// # #[cfg(feature = "default-hasher")] {
1929    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
1930    ///
1931    /// #[derive(Debug, PartialEq, Eq, Hash)]
1932    /// struct Item {
1933    ///     id: u32,
1934    ///     name: String,
1935    ///     value: u32,
1936    /// }
1937    ///
1938    /// impl BiHashItem for Item {
1939    ///     type K1<'a> = u32;
1940    ///     type K2<'a> = &'a str;
1941    ///
1942    ///     fn key1(&self) -> Self::K1<'_> {
1943    ///         self.id
1944    ///     }
1945    ///     fn key2(&self) -> Self::K2<'_> {
1946    ///         &self.name
1947    ///     }
1948    ///
1949    ///     bi_upcast!();
1950    /// }
1951    ///
1952    /// let mut map = BiHashMap::new();
1953    /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
1954    ///     .unwrap();
1955    /// map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 20 })
1956    ///     .unwrap();
1957    /// map.insert_unique(Item { id: 3, name: "baz".to_string(), value: 99 })
1958    ///     .unwrap();
1959    ///
1960    /// // Retain only items where value is greater than 30
1961    /// map.retain(|item| item.value > 30);
1962    ///
1963    /// assert_eq!(map.len(), 2);
1964    /// assert_eq!(map.get1(&1).unwrap().value, 42);
1965    /// assert_eq!(map.get1(&3).unwrap().value, 99);
1966    /// assert!(map.get1(&2).is_none());
1967    /// # }
1968    /// ```
1969    pub fn retain<'a, F>(&'a mut self, mut f: F)
1970    where
1971        F: for<'b> FnMut(RefMut<'b, T, S>) -> bool,
1972    {
1973        let hash_state = self.tables.state.clone();
1974        let (_, mut dormant_items) = DormantMutRef::new(&mut self.items);
1975        let mut removed_item = None;
1976
1977        self.tables.k1_to_item.retain(|index| {
1978            // Drop the previously-removed item here, at the top of the next
1979            // iteration.
1980            //
1981            // By now, the prior `k1_to_item` entry has been erased, so if
1982            // `drop` below panics, `k1_to_item`, `k2_to_item`, and `items`
1983            // remain in sync. Dropping the item at the end of the prior
1984            // iteration would unwind before the table erased the entry, leaving
1985            // `k1_to_item` pointing at a slot we already removed from `items`
1986            // and `k2_to_item`.
1987            drop(removed_item.take());
1988
1989            let (item, dormant_items) = {
1990                // SAFETY: All uses of `items` ended in the previous iteration.
1991                let items = unsafe { dormant_items.reborrow() };
1992                let (items, dormant_items) = DormantMutRef::new(items);
1993                let item: &'a mut T = items
1994                    .get_mut(index)
1995                    .expect("all indexes are present in self.items");
1996                (item, dormant_items)
1997            };
1998
1999            let (hashes, dormant_item) = {
2000                let (item, dormant_item): (&'a mut T, _) =
2001                    DormantMutRef::new(item);
2002                // Use T::k1(item) rather than item.key() to force the key
2003                // trait function to be called for T rather than &mut T.
2004                let key1 = T::key1(item);
2005                let key2 = T::key2(item);
2006                let hash1 = hash_state.hash_one(key1);
2007                let hash2 = hash_state.hash_one(key2);
2008                ([MapHash::new(hash1), MapHash::new(hash2)], dormant_item)
2009            };
2010
2011            let hash2 = hashes[1].hash();
2012            let retain = {
2013                // SAFETY: The original item is no longer used after the second
2014                // block above. dormant_items, from which item is derived, is
2015                // currently dormant.
2016                let item = unsafe { dormant_item.awaken() };
2017
2018                let ref_mut = RefMut::new(hash_state.clone(), hashes, item);
2019                f(ref_mut)
2020            };
2021
2022            if retain {
2023                true
2024            } else {
2025                let k2_entry = self
2026                    .tables
2027                    .k2_to_item
2028                    .find_entry_by_hash(hash2, |map2_index| {
2029                        map2_index == index
2030                    });
2031                match k2_entry {
2032                    Ok(entry) => {
2033                        entry.remove();
2034                    }
2035                    Err(_) => {
2036                        self.tables.k2_to_item.remove_by_index(index);
2037                    }
2038                }
2039
2040                // SAFETY: The original items is no longer used after the first
2041                // block above, and item + dormant_item have been dropped after
2042                // being used above. The k2 work between them borrows only
2043                // `self.tables.k2_to_item`, which is disjoint from
2044                // `self.items`.
2045                let items = unsafe { dormant_items.awaken() };
2046                removed_item = Some(
2047                    items
2048                        .remove(index)
2049                        .expect("all indexes are present in self.items"),
2050                );
2051
2052                false
2053            }
2054        });
2055
2056        // Anything in `removed_item` is implicitly dropped now.
2057    }
2058
2059    fn find1<'a, Q>(&'a self, k: &Q) -> Option<&'a T>
2060    where
2061        Q: Hash + Equivalent<T::K1<'a>> + ?Sized,
2062    {
2063        self.find1_index(k).map(|ix| &self.items[ix])
2064    }
2065
2066    fn find1_index<'a, Q>(&'a self, k: &Q) -> Option<ItemIndex>
2067    where
2068        Q: Hash + Equivalent<T::K1<'a>> + ?Sized,
2069    {
2070        self.tables
2071            .k1_to_item
2072            .find_index(&self.tables.state, k, |index| self.items[index].key1())
2073    }
2074
2075    fn find2<'a, Q>(&'a self, k: &Q) -> Option<&'a T>
2076    where
2077        Q: Hash + Equivalent<T::K2<'a>> + ?Sized,
2078    {
2079        self.find2_index(k).map(|ix| &self.items[ix])
2080    }
2081
2082    fn find2_index<'a, Q>(&'a self, k: &Q) -> Option<ItemIndex>
2083    where
2084        Q: Hash + Equivalent<T::K2<'a>> + ?Sized,
2085    {
2086        self.tables
2087            .k2_to_item
2088            .find_index(&self.tables.state, k, |index| self.items[index].key2())
2089    }
2090
2091    fn prepare_insert_overwrite(&self, value: &T) -> PreparedInsertOverwrite {
2092        let key1 = value.key1();
2093        let key2 = value.key2();
2094
2095        let index1 = self.find1_index(&key1);
2096        let index2 = self.find2_index(&key2);
2097        let hashes = self.tables.make_hashes::<T>(&key1, &key2);
2098
2099        let duplicates =
2100            PreparedDuplicate::from_indexes([index1, index2], |index| {
2101                self.prepare_duplicate(index)
2102            });
2103
2104        PreparedInsertOverwrite { index1, index2, duplicates, hashes }
2105    }
2106
2107    fn prepare_entry_index_removal(
2108        &self,
2109        indexes: EntryIndexes,
2110    ) -> Vec<PreparedDuplicate> {
2111        match indexes {
2112            EntryIndexes::Unique(index) => {
2113                PreparedDuplicate::from_indexes([Some(index)], |index| {
2114                    self.prepare_duplicate(index)
2115                })
2116            }
2117            EntryIndexes::NonUnique { index1, index2 } => {
2118                PreparedDuplicate::from_indexes([index1, index2], |index| {
2119                    self.prepare_duplicate(index)
2120                })
2121            }
2122        }
2123    }
2124
2125    fn prepare_duplicate(&self, index: ItemIndex) -> PreparedDuplicate {
2126        let item = &self.items[index];
2127        let key1 = item.key1();
2128        let key2 = item.key2();
2129        let hashes = self.tables.make_hashes::<T>(&key1, &key2);
2130
2131        PreparedDuplicate { index, hashes }
2132    }
2133
2134    fn try_reserve_insert_overwrite_commit(
2135        &mut self,
2136        needs_new_item_slot: bool,
2137    ) -> Result<(), TryReserveError> {
2138        if needs_new_item_slot {
2139            self.items.try_reserve(1)?;
2140        }
2141
2142        self.tables
2143            .k1_to_item
2144            .try_reserve(1)
2145            .map_err(TryReserveError::from_hashbrown)?;
2146        self.tables
2147            .k2_to_item
2148            .try_reserve(1)
2149            .map_err(TryReserveError::from_hashbrown)?;
2150
2151        Ok(())
2152    }
2153
2154    fn commit_insert_overwrite(
2155        &mut self,
2156        value: T,
2157        prepared: PreparedInsertOverwrite,
2158        duplicates: &mut Vec<T>,
2159    ) -> ItemIndex {
2160        // From here until insertion completes, do not call user code or
2161        // allocate. The caller prepared hashes/indexes and reserved capacity.
2162        for duplicate in prepared.duplicates {
2163            duplicates.push(
2164                self.remove_duplicate(duplicate)
2165                    .expect("duplicate index was prepared"),
2166            );
2167        }
2168
2169        self.insert_unique_with_prepared_hashes(value, prepared.hashes)
2170    }
2171
2172    fn insert_unique_with_prepared_hashes(
2173        &mut self,
2174        value: T,
2175        hashes: [MapHash; 2],
2176    ) -> ItemIndex {
2177        let [hash1, hash2] = hashes;
2178        let next_index = self.items.assert_can_grow().insert(value);
2179
2180        self.tables.k1_to_item.insert_prehashed_unchecked(hash1, next_index);
2181        self.tables.k2_to_item.insert_prehashed_unchecked(hash2, next_index);
2182
2183        next_index
2184    }
2185
2186    pub(super) fn get_by_entry_index(
2187        &self,
2188        indexes: EntryIndexes,
2189    ) -> OccupiedEntryRef<'_, T> {
2190        match indexes {
2191            EntryIndexes::Unique(index) => OccupiedEntryRef::Unique(
2192                self.items.get(index).expect("index is valid"),
2193            ),
2194            EntryIndexes::NonUnique { index1, index2 } => {
2195                let by_key1 = index1
2196                    .map(|k| self.items.get(k).expect("key1 index is valid"));
2197                let by_key2 = index2
2198                    .map(|k| self.items.get(k).expect("key2 index is valid"));
2199                OccupiedEntryRef::NonUnique { by_key1, by_key2 }
2200            }
2201        }
2202    }
2203
2204    pub(super) fn get_by_entry_index_mut(
2205        &mut self,
2206        indexes: EntryIndexes,
2207    ) -> OccupiedEntryMut<'_, T, S> {
2208        match indexes.disjoint_keys() {
2209            DisjointKeys::Unique(index) => {
2210                let item = self.items.get_mut(index).expect("index is valid");
2211                let state = self.tables.state.clone();
2212                let hashes =
2213                    self.tables.make_hashes::<T>(&item.key1(), &item.key2());
2214                OccupiedEntryMut::Unique(RefMut::new(state, hashes, item))
2215            }
2216            DisjointKeys::Key1(index1) => {
2217                let item =
2218                    self.items.get_mut(index1).expect("key1 index is valid");
2219                let state = self.tables.state.clone();
2220                let hashes =
2221                    self.tables.make_hashes::<T>(&item.key1(), &item.key2());
2222                OccupiedEntryMut::NonUnique {
2223                    by_key1: Some(RefMut::new(state, hashes, item)),
2224                    by_key2: None,
2225                }
2226            }
2227            DisjointKeys::Key2(index2) => {
2228                let item =
2229                    self.items.get_mut(index2).expect("key2 index is valid");
2230                let state = self.tables.state.clone();
2231                let hashes =
2232                    self.tables.make_hashes::<T>(&item.key1(), &item.key2());
2233                OccupiedEntryMut::NonUnique {
2234                    by_key1: None,
2235                    by_key2: Some(RefMut::new(state, hashes, item)),
2236                }
2237            }
2238            DisjointKeys::Key12(indexes) => {
2239                let state = self.tables.state.clone();
2240                let mut items = self.items.get_disjoint_mut(indexes);
2241                let item1 = items[0].take().expect("key1 index is valid");
2242                let item2 = items[1].take().expect("key2 index is valid");
2243                let hashes1 =
2244                    self.tables.make_hashes::<T>(&item1.key1(), &item1.key2());
2245                let hashes2 =
2246                    self.tables.make_hashes::<T>(&item2.key1(), &item2.key2());
2247
2248                OccupiedEntryMut::NonUnique {
2249                    by_key1: Some(RefMut::new(state.clone(), hashes1, item1)),
2250                    by_key2: Some(RefMut::new(state, hashes2, item2)),
2251                }
2252            }
2253        }
2254    }
2255
2256    pub(super) fn get_by_index_mut(
2257        &mut self,
2258        index: ItemIndex,
2259    ) -> Option<RefMut<'_, T, S>> {
2260        let borrowed = self.items.get_mut(index)?;
2261        let state = self.tables.state.clone();
2262        let hashes =
2263            self.tables.make_hashes::<T>(&borrowed.key1(), &borrowed.key2());
2264        let item = &mut self.items[index];
2265        Some(RefMut::new(state, hashes, item))
2266    }
2267
2268    pub(super) fn insert_unique_impl(
2269        &mut self,
2270        value: T,
2271    ) -> Result<ItemIndex, DuplicateItem<T, &T>> {
2272        let mut duplicates = BTreeSet::new();
2273
2274        // Check for duplicates *before* inserting the new item, because we
2275        // don't want to partially insert the new item and then have to roll
2276        // back.
2277        let state = &self.tables.state;
2278        let (e1, e2) = {
2279            let k1 = value.key1();
2280            let k2 = value.key2();
2281
2282            let e1 = detect_dup_or_insert(
2283                self.tables
2284                    .k1_to_item
2285                    .entry(state, k1, |index| self.items[index].key1()),
2286                &mut duplicates,
2287            );
2288            let e2 = detect_dup_or_insert(
2289                self.tables
2290                    .k2_to_item
2291                    .entry(state, k2, |index| self.items[index].key2()),
2292                &mut duplicates,
2293            );
2294            (e1, e2)
2295        };
2296
2297        if !duplicates.is_empty() {
2298            return Err(DuplicateItem::__internal_new(
2299                value,
2300                duplicates.iter().map(|ix| &self.items[*ix]).collect(),
2301            ));
2302        }
2303
2304        let next_index = self.items.assert_can_grow().insert(value);
2305        // e1 and e2 are all Some because if they were None, duplicates
2306        // would be non-empty, and we'd have bailed out earlier.
2307        e1.unwrap().insert(next_index);
2308        e2.unwrap().insert(next_index);
2309
2310        Ok(next_index)
2311    }
2312
2313    pub(super) fn remove_by_entry_index(
2314        &mut self,
2315        indexes: EntryIndexes,
2316    ) -> Vec<T> {
2317        let prepared = self.prepare_entry_index_removal(indexes);
2318        let mut old_items = Vec::with_capacity(prepared.len());
2319
2320        for duplicate in prepared {
2321            old_items.push(
2322                self.remove_duplicate(duplicate)
2323                    .expect("prepared duplicate index was present"),
2324            );
2325        }
2326
2327        old_items
2328    }
2329
2330    pub(super) fn remove_by_index(
2331        &mut self,
2332        remove_index: ItemIndex,
2333    ) -> Option<T> {
2334        // For panic safety, compute both key hashes and look up both table
2335        // entries while `self.items` still holds the value, then remove from
2336        // both tables and items in sequence. These lookups deliberately match
2337        // by `ItemIndex` rather than by user `Eq`: at this point we already
2338        // know which item is being removed, and user `Eq` might be
2339        // pathological. hashbrown's `find_entry_by_hash` is panic-safe because
2340        // the table is not mutated until `OccupiedEntry::remove` is called, so
2341        // a panic while hashing leaves items and both tables unmodified.
2342        // (Unlike the IdOrdMap path, no separate two-phase commit is needed:
2343        // the BTreeMap analog has to guard against a user-`Ord` panic during
2344        // the tree walk, but the hash walk here never invokes user code.)
2345        //
2346        // If either hash lookup misses — which happens when a `mem::forget`
2347        // on a `RefMut` bypassed the drop-time hash check and one of the
2348        // item's keys now hashes to a different bucket than its entry sits
2349        // in — fall back to a linear scan by `ItemIndex` for that table.
2350        // The fallback never invokes user `Hash`, so cleanup remains
2351        // panic-safe.
2352        let item = self.items.get(remove_index)?;
2353        let state = &self.tables.state;
2354        let hash1 = state.hash_one(item.key1());
2355        let hash2 = state.hash_one(item.key2());
2356        match self
2357            .tables
2358            .k1_to_item
2359            .find_entry_by_hash(hash1, |index| index == remove_index)
2360        {
2361            Ok(entry) => entry.remove(),
2362            Err(()) => self.tables.k1_to_item.remove_by_index(remove_index),
2363        }
2364        match self
2365            .tables
2366            .k2_to_item
2367            .find_entry_by_hash(hash2, |index| index == remove_index)
2368        {
2369            Ok(entry) => entry.remove(),
2370            Err(()) => self.tables.k2_to_item.remove_by_index(remove_index),
2371        }
2372        Some(
2373            self.items
2374                .remove(remove_index)
2375                .expect("items[remove_index] was Occupied above"),
2376        )
2377    }
2378
2379    /// Removes the item at `duplicate`, using already-computed key hashes when
2380    /// possible.
2381    ///
2382    /// The caller must ensure:
2383    ///
2384    /// * all user-controlled key extraction and hashing for the item at
2385    ///   `duplicate.index` has already completed;
2386    /// * the item at `duplicate.index` has not changed since those hashes were
2387    ///   computed;
2388    /// * removing this index from the item store and key tables preserves the
2389    ///   map/table invariants.
2390    ///
2391    /// The provided `duplicate.hashes` allow the normal commit path to remove
2392    /// key-table entries without recomputing user-controlled hashes. If a
2393    /// prehashed lookup misses, this falls back to removing by `ItemIndex`,
2394    /// which performs a linear scan over cached indexes and does not re-enter
2395    /// user code.
2396    fn remove_duplicate(&mut self, duplicate: PreparedDuplicate) -> Option<T> {
2397        let _ = self.items.get(duplicate.index)?;
2398
2399        let [hash1, hash2] = duplicate.hashes;
2400
2401        match self
2402            .tables
2403            .k1_to_item
2404            .find_entry_by_hash(hash1.hash(), |index| index == duplicate.index)
2405        {
2406            Ok(entry) => entry.remove(),
2407            Err(()) => self.tables.k1_to_item.remove_by_index(duplicate.index),
2408        }
2409
2410        match self
2411            .tables
2412            .k2_to_item
2413            .find_entry_by_hash(hash2.hash(), |index| index == duplicate.index)
2414        {
2415            Ok(entry) => entry.remove(),
2416            Err(()) => self.tables.k2_to_item.remove_by_index(duplicate.index),
2417        }
2418
2419        Some(
2420            self.items
2421                .remove(duplicate.index)
2422                .expect("items[duplicate.index] was Occupied above"),
2423        )
2424    }
2425
2426    pub(super) fn replace_at_indexes(
2427        &mut self,
2428        indexes: EntryIndexes,
2429        value: T,
2430    ) -> (ItemIndex, Vec<T>) {
2431        match indexes {
2432            EntryIndexes::Unique(index) => {
2433                {
2434                    let old_item = &self.items[index];
2435                    if old_item.key1() != value.key1() {
2436                        panic!("key1 mismatch");
2437                    }
2438                    if old_item.key2() != value.key2() {
2439                        panic!("key2 mismatch");
2440                    }
2441                }
2442
2443                let mut old_items = Vec::with_capacity(1);
2444                let old_item = self.items.replace(index, value);
2445                old_items.push(old_item);
2446
2447                (index, old_items)
2448            }
2449            EntryIndexes::NonUnique { index1, index2 } => {
2450                let prepared = self.prepare_insert_overwrite(&value);
2451
2452                if prepared.index1 != index1 {
2453                    panic!("key1 mismatch");
2454                }
2455                if prepared.index2 != index2 {
2456                    panic!("key2 mismatch");
2457                }
2458
2459                let mut old_items =
2460                    Vec::with_capacity(prepared.duplicate_count());
2461
2462                self.try_reserve_insert_overwrite_commit(
2463                    prepared.needs_new_item_slot(),
2464                )
2465                .expect("reserved item slot");
2466
2467                let next_index = self.commit_insert_overwrite(
2468                    value,
2469                    prepared,
2470                    &mut old_items,
2471                );
2472
2473                (next_index, old_items)
2474            }
2475        }
2476    }
2477}
2478
2479impl<'a, T, S, A> fmt::Debug for BiHashMap<T, S, A>
2480where
2481    T: BiHashItem + fmt::Debug,
2482    T::K1<'a>: fmt::Debug,
2483    T::K2<'a>: fmt::Debug,
2484    T: 'a,
2485    A: Allocator,
2486{
2487    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2488        let mut map = f.debug_map();
2489        for item in self.items.values() {
2490            let key: KeyMap<'_, T> =
2491                KeyMap { key1: item.key1(), key2: item.key2() };
2492
2493            // SAFETY:
2494            //
2495            // * Lifetime extension: for a type T and two lifetime params 'a and
2496            //   'b, T<'a> and T<'b> aren't guaranteed to have the same layout,
2497            //   but (a) that is true today and (b) it would be shocking and
2498            //   break half the Rust ecosystem if that were to change in the
2499            //   future.
2500            // * We only use key within the scope of this block before immediately
2501            //   dropping it. In particular, map.entry calls key.fmt() without
2502            //   holding a reference to it.
2503            let key: KeyMap<'a, T> = unsafe {
2504                core::mem::transmute::<KeyMap<'_, T>, KeyMap<'a, T>>(key)
2505            };
2506
2507            map.entry(&key as &dyn fmt::Debug, item);
2508        }
2509        map.finish()
2510    }
2511}
2512
2513struct KeyMap<'a, T: BiHashItem + 'a> {
2514    key1: T::K1<'a>,
2515    key2: T::K2<'a>,
2516}
2517
2518impl<'a, T: BiHashItem + 'a> fmt::Debug for KeyMap<'a, T>
2519where
2520    T::K1<'a>: fmt::Debug,
2521    T::K2<'a>: fmt::Debug,
2522{
2523    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2524        // We don't want to show key1 and key2 as a tuple since it's
2525        // misleading (suggests maps of tuples). The best we can do
2526        // instead is to show "{k1: "abc", k2: "xyz"}"
2527        f.debug_map()
2528            .entry(&StrDisplayAsDebug("k1"), &self.key1)
2529            .entry(&StrDisplayAsDebug("k2"), &self.key2)
2530            .finish()
2531    }
2532}
2533
2534/// The `PartialEq` implementation for `BiHashMap` checks that both maps have
2535/// the same items, regardless of insertion order.
2536///
2537/// # Examples
2538///
2539/// ```
2540/// # #[cfg(feature = "default-hasher")] {
2541/// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
2542///
2543/// #[derive(Debug, PartialEq, Eq)]
2544/// struct Item {
2545///     id: u32,
2546///     name: String,
2547///     value: i32,
2548/// }
2549///
2550/// impl BiHashItem for Item {
2551///     type K1<'a> = u32;
2552///     type K2<'a> = &'a str;
2553///
2554///     fn key1(&self) -> Self::K1<'_> {
2555///         self.id
2556///     }
2557///     fn key2(&self) -> Self::K2<'_> {
2558///         &self.name
2559///     }
2560///     bi_upcast!();
2561/// }
2562///
2563/// let mut map1 = BiHashMap::new();
2564/// map1.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
2565///     .unwrap();
2566/// map1.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
2567///     .unwrap();
2568///
2569/// let mut map2 = BiHashMap::new();
2570/// map2.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
2571///     .unwrap();
2572/// map2.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
2573///     .unwrap();
2574///
2575/// // Maps are equal even if items were inserted in different order
2576/// assert_eq!(map1, map2);
2577///
2578/// map2.insert_unique(Item { id: 3, name: "baz".to_string(), value: 200 })
2579///     .unwrap();
2580/// assert_ne!(map1, map2);
2581/// # }
2582/// ```
2583impl<T: BiHashItem + PartialEq, S: Clone + BuildHasher, A: Allocator> PartialEq
2584    for BiHashMap<T, S, A>
2585{
2586    fn eq(&self, other: &Self) -> bool {
2587        // Implementing PartialEq for BiHashMap is tricky because BiHashMap is
2588        // not semantically like an IndexMap: two maps are equivalent even if
2589        // their items are in a different order. In other words, any permutation
2590        // of items is equivalent.
2591        //
2592        // We also can't sort the items because they're not necessarily Ord.
2593        //
2594        // So we write a custom equality check that checks that each key in one
2595        // map points to the same item as in the other map.
2596
2597        if self.items.len() != other.items.len() {
2598            return false;
2599        }
2600
2601        // Walk over all the items in the first map and check that they point to
2602        // the same item in the second map.
2603        for item in self.items.values() {
2604            let k1 = item.key1();
2605            let k2 = item.key2();
2606
2607            // Check that the indexes are the same in the other map.
2608            let Some(other_ix1) = other.find1_index(&k1) else {
2609                return false;
2610            };
2611            let Some(other_ix2) = other.find2_index(&k2) else {
2612                return false;
2613            };
2614
2615            if other_ix1 != other_ix2 {
2616                // All the keys were present but they didn't point to the same
2617                // item.
2618                return false;
2619            }
2620
2621            // Check that the other map's item is the same as this map's
2622            // item. (This is what we use the `PartialEq` bound on T for.)
2623            //
2624            // Because we've checked that other_ix1 and other_ix2 are
2625            // Some, we know that it is valid and points to the expected item.
2626            let other_item = &other.items[other_ix1];
2627            if item != other_item {
2628                return false;
2629            }
2630        }
2631
2632        true
2633    }
2634}
2635
2636// The Eq bound on T ensures that the BiHashMap forms an equivalence class.
2637impl<T: BiHashItem + Eq, S: Clone + BuildHasher, A: Allocator> Eq
2638    for BiHashMap<T, S, A>
2639{
2640}
2641
2642fn detect_dup_or_insert<'a, A: Allocator>(
2643    item: hash_table::Entry<'a, A>,
2644    duplicates: &mut BTreeSet<ItemIndex>,
2645) -> Option<hash_table::VacantEntry<'a, A>> {
2646    match item {
2647        hash_table::Entry::Vacant(slot) => Some(slot),
2648        hash_table::Entry::Occupied(slot) => {
2649            duplicates.insert(slot.get());
2650            None
2651        }
2652    }
2653}
2654
2655/// The `Extend` implementation overwrites duplicates. In the future, there will
2656/// also be an `extend_unique` method that will return an error.
2657///
2658/// # Examples
2659///
2660/// ```
2661/// # #[cfg(feature = "default-hasher")] {
2662/// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
2663///
2664/// #[derive(Debug, PartialEq, Eq)]
2665/// struct Item {
2666///     id: u32,
2667///     name: String,
2668///     value: i32,
2669/// }
2670///
2671/// impl BiHashItem for Item {
2672///     type K1<'a> = u32;
2673///     type K2<'a> = &'a str;
2674///
2675///     fn key1(&self) -> Self::K1<'_> {
2676///         self.id
2677///     }
2678///     fn key2(&self) -> Self::K2<'_> {
2679///         &self.name
2680///     }
2681///     bi_upcast!();
2682/// }
2683///
2684/// let mut map = BiHashMap::new();
2685/// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 }).unwrap();
2686///
2687/// let new_items = vec![
2688///     Item { id: 2, name: "bar".to_string(), value: 99 },
2689///     Item { id: 1, name: "baz".to_string(), value: 100 }, // overwrites existing
2690/// ];
2691///
2692/// map.extend(new_items);
2693/// assert_eq!(map.len(), 2);
2694/// assert_eq!(map.get1(&1).unwrap().name, "baz"); // overwritten
2695/// assert_eq!(map.get1(&1).unwrap().value, 100);
2696/// # }
2697/// ```
2698impl<T: BiHashItem, S: Clone + BuildHasher, A: Allocator> Extend<T>
2699    for BiHashMap<T, S, A>
2700{
2701    fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
2702        // Keys may already be present in the map, or multiple times in the
2703        // iterator. Reserve the entire hint lower bound if the map is empty.
2704        // Otherwise reserve half the hint (rounded up), so the map will only
2705        // resize twice in the worst case.
2706        let iter = iter.into_iter();
2707        let reserve = if self.is_empty() {
2708            iter.size_hint().0
2709        } else {
2710            iter.size_hint().0.div_ceil(2)
2711        };
2712        self.reserve(reserve);
2713        for item in iter {
2714            self.insert_overwrite(item);
2715        }
2716    }
2717}
2718
2719impl<'a, T: BiHashItem, S: Clone + BuildHasher, A: Allocator> IntoIterator
2720    for &'a BiHashMap<T, S, A>
2721{
2722    type Item = &'a T;
2723    type IntoIter = Iter<'a, T>;
2724
2725    #[inline]
2726    fn into_iter(self) -> Self::IntoIter {
2727        self.iter()
2728    }
2729}
2730
2731impl<'a, T: BiHashItem, S: Clone + BuildHasher, A: Allocator> IntoIterator
2732    for &'a mut BiHashMap<T, S, A>
2733{
2734    type Item = RefMut<'a, T, S>;
2735    type IntoIter = IterMut<'a, T, S, A>;
2736
2737    #[inline]
2738    fn into_iter(self) -> Self::IntoIter {
2739        self.iter_mut()
2740    }
2741}
2742
2743impl<T: BiHashItem, S: Clone + BuildHasher, A: Allocator> IntoIterator
2744    for BiHashMap<T, S, A>
2745{
2746    type Item = T;
2747    type IntoIter = IntoIter<T, A>;
2748
2749    #[inline]
2750    fn into_iter(self) -> Self::IntoIter {
2751        IntoIter::new(self.items)
2752    }
2753}
2754
2755/// The `FromIterator` implementation for `BiHashMap` overwrites duplicate
2756/// items.
2757///
2758/// # Examples
2759///
2760/// ```
2761/// # #[cfg(feature = "default-hasher")] {
2762/// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
2763///
2764/// #[derive(Debug, PartialEq, Eq)]
2765/// struct Item {
2766///     id: u32,
2767///     name: String,
2768///     value: i32,
2769/// }
2770///
2771/// impl BiHashItem for Item {
2772///     type K1<'a> = u32;
2773///     type K2<'a> = &'a str;
2774///
2775///     fn key1(&self) -> Self::K1<'_> {
2776///         self.id
2777///     }
2778///     fn key2(&self) -> Self::K2<'_> {
2779///         &self.name
2780///     }
2781///     bi_upcast!();
2782/// }
2783///
2784/// let items = vec![
2785///     Item { id: 1, name: "foo".to_string(), value: 42 },
2786///     Item { id: 2, name: "bar".to_string(), value: 99 },
2787///     Item { id: 1, name: "baz".to_string(), value: 100 }, // overwrites first item
2788/// ];
2789///
2790/// let map: BiHashMap<Item> = items.into_iter().collect();
2791/// assert_eq!(map.len(), 2);
2792/// assert_eq!(map.get1(&1).unwrap().name, "baz"); // overwritten
2793/// assert_eq!(map.get1(&1).unwrap().value, 100);
2794/// assert_eq!(map.get1(&2).unwrap().value, 99);
2795/// # }
2796/// ```
2797impl<T: BiHashItem, S: Clone + BuildHasher + Default, A: Default + Allocator>
2798    FromIterator<T> for BiHashMap<T, S, A>
2799{
2800    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
2801        let mut map = BiHashMap::default();
2802        map.extend(iter);
2803        map
2804    }
2805}