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