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