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