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    /// Returns an iterator over all items in the map.
715    ///
716    /// Similar to [`HashMap`], the iteration order is arbitrary and not
717    /// guaranteed to be stable.
718    ///
719    /// [`HashMap`]: std::collections::HashMap
720    /// # Examples
721    ///
722    /// ```
723    /// # #[cfg(feature = "default-hasher")] {
724    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
725    ///
726    /// #[derive(Debug, PartialEq, Eq)]
727    /// struct Item {
728    ///     id: u32,
729    ///     name: String,
730    ///     value: i32,
731    /// }
732    ///
733    /// impl BiHashItem for Item {
734    ///     type K1<'a> = u32;
735    ///     type K2<'a> = &'a str;
736    ///
737    ///     fn key1(&self) -> Self::K1<'_> {
738    ///         self.id
739    ///     }
740    ///     fn key2(&self) -> Self::K2<'_> {
741    ///         &self.name
742    ///     }
743    ///     bi_upcast!();
744    /// }
745    ///
746    /// let mut map = BiHashMap::new();
747    /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
748    ///     .unwrap();
749    /// map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
750    ///     .unwrap();
751    ///
752    /// let mut values: Vec<i32> = map.iter().map(|item| item.value).collect();
753    /// values.sort();
754    /// assert_eq!(values, vec![42, 99]);
755    /// # }
756    /// ```
757    #[inline]
758    pub fn iter(&self) -> Iter<'_, T> {
759        Iter::new(&self.items)
760    }
761
762    /// Iterates over the items in the map, allowing for mutation.
763    ///
764    /// Similar to [`HashMap`], the iteration order is arbitrary and not
765    /// guaranteed to be stable.
766    ///
767    /// # Examples
768    ///
769    /// ```
770    /// # #[cfg(feature = "default-hasher")] {
771    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
772    ///
773    /// #[derive(Debug, PartialEq, Eq)]
774    /// struct Item {
775    ///     id: u32,
776    ///     name: String,
777    ///     value: i32,
778    /// }
779    ///
780    /// impl BiHashItem for Item {
781    ///     type K1<'a> = u32;
782    ///     type K2<'a> = &'a str;
783    ///
784    ///     fn key1(&self) -> Self::K1<'_> {
785    ///         self.id
786    ///     }
787    ///     fn key2(&self) -> Self::K2<'_> {
788    ///         &self.name
789    ///     }
790    ///     bi_upcast!();
791    /// }
792    ///
793    /// let mut map = BiHashMap::new();
794    /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
795    ///     .unwrap();
796    /// map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
797    ///     .unwrap();
798    ///
799    /// for mut item in map.iter_mut() {
800    ///     item.value += 10;
801    /// }
802    ///
803    /// assert_eq!(map.get1(&1).unwrap().value, 52);
804    /// assert_eq!(map.get1(&2).unwrap().value, 109);
805    /// # }
806    /// ```
807    ///
808    /// [`HashMap`]: std::collections::HashMap
809    #[inline]
810    pub fn iter_mut(&mut self) -> IterMut<'_, T, S, A> {
811        IterMut::new(&self.tables, &mut self.items)
812    }
813
814    /// Checks general invariants of the map.
815    ///
816    /// The code below always upholds these invariants, but it's useful to have
817    /// an explicit check for tests.
818    #[doc(hidden)]
819    pub fn validate(
820        &self,
821        compactness: ValidateCompact,
822    ) -> Result<(), ValidationError>
823    where
824        T: fmt::Debug,
825    {
826        self.items.validate(compactness)?;
827        self.tables.validate(self.len(), compactness)?;
828
829        // Check that the indexes are all correct.
830        for (&ix, item) in self.items.iter() {
831            let key1 = item.key1();
832            let key2 = item.key2();
833
834            let Some(ix1) = self.find1_index(&key1) else {
835                return Err(ValidationError::general(format!(
836                    "item at index {ix} has no key1 index"
837                )));
838            };
839            let Some(ix2) = self.find2_index(&key2) else {
840                return Err(ValidationError::general(format!(
841                    "item at index {ix} has no key2 index"
842                )));
843            };
844
845            if ix1 != ix || ix2 != ix {
846                return Err(ValidationError::general(format!(
847                    "item at index {ix} has inconsistent indexes: {ix1}/{ix2}"
848                )));
849            }
850        }
851
852        Ok(())
853    }
854
855    /// Inserts a value into the map, removing any conflicting items and
856    /// returning a list of those items.
857    ///
858    /// # Examples
859    ///
860    /// ```
861    /// # #[cfg(feature = "default-hasher")] {
862    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
863    ///
864    /// #[derive(Debug, PartialEq, Eq)]
865    /// struct Item {
866    ///     id: u32,
867    ///     name: String,
868    ///     value: i32,
869    /// }
870    ///
871    /// impl BiHashItem for Item {
872    ///     type K1<'a> = u32;
873    ///     type K2<'a> = &'a str;
874    ///
875    ///     fn key1(&self) -> Self::K1<'_> {
876    ///         self.id
877    ///     }
878    ///     fn key2(&self) -> Self::K2<'_> {
879    ///         &self.name
880    ///     }
881    ///     bi_upcast!();
882    /// }
883    ///
884    /// let mut map = BiHashMap::new();
885    /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
886    ///     .unwrap();
887    /// map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
888    ///     .unwrap();
889    ///
890    /// // Insert an item with conflicting key1
891    /// let removed = map.insert_overwrite(Item {
892    ///     id: 1,
893    ///     name: "baz".to_string(),
894    ///     value: 100,
895    /// });
896    /// assert_eq!(removed.len(), 1);
897    /// assert_eq!(removed[0].name, "foo");
898    /// assert_eq!(removed[0].value, 42);
899    ///
900    /// assert_eq!(map.len(), 2);
901    /// assert_eq!(map.get1(&1).unwrap().name, "baz");
902    /// # }
903    /// ```
904    #[doc(alias = "insert")]
905    pub fn insert_overwrite(&mut self, value: T) -> Vec<T> {
906        // Trying to write this function for maximal efficiency can get very
907        // tricky, requiring delicate handling of indexes. We follow a very
908        // simple approach instead:
909        //
910        // 1. Remove items corresponding to keys that are already in the map.
911        // 2. Add the item to the map.
912
913        let mut duplicates = Vec::new();
914        duplicates.extend(self.remove1(&value.key1()));
915        duplicates.extend(self.remove2(&value.key2()));
916
917        if self.insert_unique(value).is_err() {
918            // We should never get here, because we just removed all the
919            // duplicates.
920            panic!("insert_unique failed after removing duplicates");
921        }
922
923        duplicates
924    }
925
926    /// Inserts a value into the set, returning an error if any duplicates were
927    /// added.
928    ///
929    /// # Examples
930    ///
931    /// ```
932    /// # #[cfg(feature = "default-hasher")] {
933    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
934    ///
935    /// #[derive(Debug, PartialEq, Eq)]
936    /// struct Item {
937    ///     id: u32,
938    ///     name: String,
939    ///     value: i32,
940    /// }
941    ///
942    /// impl BiHashItem for Item {
943    ///     type K1<'a> = u32;
944    ///     type K2<'a> = &'a str;
945    ///
946    ///     fn key1(&self) -> Self::K1<'_> {
947    ///         self.id
948    ///     }
949    ///     fn key2(&self) -> Self::K2<'_> {
950    ///         &self.name
951    ///     }
952    ///     bi_upcast!();
953    /// }
954    ///
955    /// let mut map = BiHashMap::new();
956    ///
957    /// // Successful insertion
958    /// assert!(
959    ///     map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
960    ///         .is_ok()
961    /// );
962    /// assert!(
963    ///     map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
964    ///         .is_ok()
965    /// );
966    ///
967    /// // Duplicate key1
968    /// assert!(
969    ///     map.insert_unique(Item { id: 1, name: "baz".to_string(), value: 100 })
970    ///         .is_err()
971    /// );
972    ///
973    /// // Duplicate key2
974    /// assert!(
975    ///     map.insert_unique(Item { id: 3, name: "foo".to_string(), value: 200 })
976    ///         .is_err()
977    /// );
978    /// # }
979    /// ```
980    pub fn insert_unique(
981        &mut self,
982        value: T,
983    ) -> Result<(), DuplicateItem<T, &T>> {
984        let _ = self.insert_unique_impl(value)?;
985        Ok(())
986    }
987
988    /// Returns true if the map contains a single item that matches both `key1` and `key2`.
989    ///
990    /// # Examples
991    ///
992    /// ```
993    /// # #[cfg(feature = "default-hasher")] {
994    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
995    ///
996    /// #[derive(Debug, PartialEq, Eq)]
997    /// struct Item {
998    ///     id: u32,
999    ///     name: String,
1000    ///     value: i32,
1001    /// }
1002    ///
1003    /// impl BiHashItem for Item {
1004    ///     type K1<'a> = u32;
1005    ///     type K2<'a> = &'a str;
1006    ///
1007    ///     fn key1(&self) -> Self::K1<'_> {
1008    ///         self.id
1009    ///     }
1010    ///     fn key2(&self) -> Self::K2<'_> {
1011    ///         &self.name
1012    ///     }
1013    ///     bi_upcast!();
1014    /// }
1015    ///
1016    /// let mut map = BiHashMap::new();
1017    /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 }).unwrap();
1018    /// map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 }).unwrap();
1019    ///
1020    /// assert!(map.contains_key_unique(&1, &"foo"));
1021    /// assert!(map.contains_key_unique(&2, &"bar"));
1022    /// assert!(!map.contains_key_unique(&1, &"bar")); // key1 exists but key2 doesn't match
1023    /// assert!(!map.contains_key_unique(&3, &"baz")); // neither key exists
1024    /// # }
1025    /// ```
1026    pub fn contains_key_unique<'a, Q1, Q2>(
1027        &'a self,
1028        key1: &Q1,
1029        key2: &Q2,
1030    ) -> bool
1031    where
1032        Q1: Hash + Equivalent<T::K1<'a>> + ?Sized,
1033        Q2: Hash + Equivalent<T::K2<'a>> + ?Sized,
1034    {
1035        self.get_unique(key1, key2).is_some()
1036    }
1037
1038    /// Gets a reference to the unique item associated with the given `key1` and
1039    /// `key2`, if it exists.
1040    ///
1041    /// # Examples
1042    ///
1043    /// ```
1044    /// # #[cfg(feature = "default-hasher")] {
1045    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
1046    ///
1047    /// #[derive(Debug, PartialEq, Eq)]
1048    /// struct Item {
1049    ///     id: u32,
1050    ///     name: String,
1051    ///     value: i32,
1052    /// }
1053    ///
1054    /// impl BiHashItem for Item {
1055    ///     type K1<'a> = u32;
1056    ///     type K2<'a> = &'a str;
1057    ///
1058    ///     fn key1(&self) -> Self::K1<'_> {
1059    ///         self.id
1060    ///     }
1061    ///     fn key2(&self) -> Self::K2<'_> {
1062    ///         &self.name
1063    ///     }
1064    ///     bi_upcast!();
1065    /// }
1066    ///
1067    /// let mut map = BiHashMap::new();
1068    /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 }).unwrap();
1069    /// map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 }).unwrap();
1070    ///
1071    /// assert_eq!(map.get_unique(&1, &"foo").unwrap().value, 42);
1072    /// assert_eq!(map.get_unique(&2, &"bar").unwrap().value, 99);
1073    /// assert!(map.get_unique(&1, &"bar").is_none()); // key1 exists but key2 doesn't match
1074    /// assert!(map.get_unique(&3, &"baz").is_none()); // neither key exists
1075    /// # }
1076    /// ```
1077    pub fn get_unique<'a, Q1, Q2>(
1078        &'a self,
1079        key1: &Q1,
1080        key2: &Q2,
1081    ) -> Option<&'a T>
1082    where
1083        Q1: Hash + Equivalent<T::K1<'a>> + ?Sized,
1084        Q2: Hash + Equivalent<T::K2<'a>> + ?Sized,
1085    {
1086        let index = self.find1_index(key1)?;
1087        let item = &self.items[index];
1088        if key2.equivalent(&item.key2()) { Some(item) } else { None }
1089    }
1090
1091    /// Gets a mutable reference to the unique item associated with the given
1092    /// `key1` and `key2`, if it exists.
1093    pub fn get_mut_unique<'a, Q1, Q2>(
1094        &'a mut self,
1095        key1: &Q1,
1096        key2: &Q2,
1097    ) -> Option<RefMut<'a, T, S>>
1098    where
1099        Q1: Hash + Equivalent<T::K1<'a>> + ?Sized,
1100        Q2: Hash + Equivalent<T::K2<'a>> + ?Sized,
1101    {
1102        let (dormant_map, index) = {
1103            let (map, dormant_map) = DormantMutRef::new(self);
1104            let index = map.find1_index(key1)?;
1105            // Check key2 match before proceeding
1106            if !key2.equivalent(&map.items[index].key2()) {
1107                return None;
1108            }
1109            (dormant_map, index)
1110        };
1111
1112        // SAFETY: `map` is not used after this point.
1113        let awakened_map = unsafe { dormant_map.awaken() };
1114        let item = &mut awakened_map.items[index];
1115        let state = awakened_map.tables.state.clone();
1116        let hashes =
1117            awakened_map.tables.make_hashes::<T>(&item.key1(), &item.key2());
1118        Some(RefMut::new(state, hashes, item))
1119    }
1120
1121    /// Removes the item uniquely identified by `key1` and `key2`, if it exists.
1122    pub fn remove_unique<'a, Q1, Q2>(
1123        &'a mut self,
1124        key1: &Q1,
1125        key2: &Q2,
1126    ) -> Option<T>
1127    where
1128        Q1: Hash + Equivalent<T::K1<'a>> + ?Sized,
1129        Q2: Hash + Equivalent<T::K2<'a>> + ?Sized,
1130    {
1131        let (dormant_map, remove_index) = {
1132            let (map, dormant_map) = DormantMutRef::new(self);
1133            let remove_index = map.find1_index(key1)?;
1134            if !key2.equivalent(&map.items[remove_index].key2()) {
1135                return None;
1136            }
1137            (dormant_map, remove_index)
1138        };
1139
1140        // SAFETY: `map` is not used after this point.
1141        let awakened_map = unsafe { dormant_map.awaken() };
1142
1143        awakened_map.remove_by_index(remove_index)
1144    }
1145
1146    /// Returns true if the map contains the given `key1`.
1147    ///
1148    /// # Examples
1149    ///
1150    /// ```
1151    /// # #[cfg(feature = "default-hasher")] {
1152    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
1153    ///
1154    /// #[derive(Debug, PartialEq, Eq)]
1155    /// struct Item {
1156    ///     id: u32,
1157    ///     name: String,
1158    ///     value: i32,
1159    /// }
1160    ///
1161    /// impl BiHashItem for Item {
1162    ///     type K1<'a> = u32;
1163    ///     type K2<'a> = &'a str;
1164    ///
1165    ///     fn key1(&self) -> Self::K1<'_> {
1166    ///         self.id
1167    ///     }
1168    ///     fn key2(&self) -> Self::K2<'_> {
1169    ///         &self.name
1170    ///     }
1171    ///     bi_upcast!();
1172    /// }
1173    ///
1174    /// let mut map = BiHashMap::new();
1175    /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
1176    ///     .unwrap();
1177    /// map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
1178    ///     .unwrap();
1179    ///
1180    /// assert!(map.contains_key1(&1));
1181    /// assert!(map.contains_key1(&2));
1182    /// assert!(!map.contains_key1(&3));
1183    /// # }
1184    /// ```
1185    pub fn contains_key1<'a, Q>(&'a self, key1: &Q) -> bool
1186    where
1187        Q: Hash + Equivalent<T::K1<'a>> + ?Sized,
1188    {
1189        self.find1_index(key1).is_some()
1190    }
1191
1192    /// Gets a reference to the value associated with the given `key1`.
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 })
1222    ///     .unwrap();
1223    /// map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
1224    ///     .unwrap();
1225    ///
1226    /// assert_eq!(map.get1(&1).unwrap().value, 42);
1227    /// assert_eq!(map.get1(&2).unwrap().value, 99);
1228    /// assert!(map.get1(&3).is_none());
1229    /// # }
1230    /// ```
1231    pub fn get1<'a, Q>(&'a self, key1: &Q) -> Option<&'a T>
1232    where
1233        Q: Hash + Equivalent<T::K1<'a>> + ?Sized,
1234    {
1235        self.find1(key1)
1236    }
1237
1238    /// Gets a mutable reference to the value associated with the given `key1`.
1239    pub fn get1_mut<'a, Q>(&'a mut self, key1: &Q) -> Option<RefMut<'a, T, S>>
1240    where
1241        Q: Hash + Equivalent<T::K1<'a>> + ?Sized,
1242    {
1243        let (dormant_map, index) = {
1244            let (map, dormant_map) = DormantMutRef::new(self);
1245            let index = map.find1_index(key1)?;
1246            (dormant_map, index)
1247        };
1248
1249        // SAFETY: `map` is not used after this point.
1250        let awakened_map = unsafe { dormant_map.awaken() };
1251        let item = &mut awakened_map.items[index];
1252        let state = awakened_map.tables.state.clone();
1253        let hashes =
1254            awakened_map.tables.make_hashes::<T>(&item.key1(), &item.key2());
1255        Some(RefMut::new(state, hashes, item))
1256    }
1257
1258    /// Removes an item from the map by its `key1`.
1259    ///
1260    /// # Examples
1261    ///
1262    /// ```
1263    /// # #[cfg(feature = "default-hasher")] {
1264    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
1265    ///
1266    /// #[derive(Debug, PartialEq, Eq)]
1267    /// struct Item {
1268    ///     id: u32,
1269    ///     name: String,
1270    ///     value: i32,
1271    /// }
1272    ///
1273    /// impl BiHashItem for Item {
1274    ///     type K1<'a> = u32;
1275    ///     type K2<'a> = &'a str;
1276    ///
1277    ///     fn key1(&self) -> Self::K1<'_> {
1278    ///         self.id
1279    ///     }
1280    ///     fn key2(&self) -> Self::K2<'_> {
1281    ///         &self.name
1282    ///     }
1283    ///     bi_upcast!();
1284    /// }
1285    ///
1286    /// let mut map = BiHashMap::new();
1287    /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
1288    ///     .unwrap();
1289    /// map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
1290    ///     .unwrap();
1291    ///
1292    /// let removed = map.remove1(&1);
1293    /// assert_eq!(removed.unwrap().value, 42);
1294    /// assert_eq!(map.len(), 1);
1295    /// assert!(map.get1(&1).is_none());
1296    /// assert!(map.remove1(&3).is_none());
1297    /// # }
1298    /// ```
1299    pub fn remove1<'a, Q>(&'a mut self, key1: &Q) -> Option<T>
1300    where
1301        Q: Hash + Equivalent<T::K1<'a>> + ?Sized,
1302    {
1303        let (dormant_map, remove_index) = {
1304            let (map, dormant_map) = DormantMutRef::new(self);
1305            let remove_index = map.find1_index(key1)?;
1306            (dormant_map, remove_index)
1307        };
1308
1309        // SAFETY: `map` is not used after this point.
1310        let awakened_map = unsafe { dormant_map.awaken() };
1311
1312        awakened_map.remove_by_index(remove_index)
1313    }
1314
1315    /// Returns true if the map contains the given `key2`.
1316    ///
1317    /// # Examples
1318    ///
1319    /// ```
1320    /// # #[cfg(feature = "default-hasher")] {
1321    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
1322    ///
1323    /// #[derive(Debug, PartialEq, Eq)]
1324    /// struct Item {
1325    ///     id: u32,
1326    ///     name: String,
1327    ///     value: i32,
1328    /// }
1329    ///
1330    /// impl BiHashItem for Item {
1331    ///     type K1<'a> = u32;
1332    ///     type K2<'a> = &'a str;
1333    ///
1334    ///     fn key1(&self) -> Self::K1<'_> {
1335    ///         self.id
1336    ///     }
1337    ///     fn key2(&self) -> Self::K2<'_> {
1338    ///         &self.name
1339    ///     }
1340    ///     bi_upcast!();
1341    /// }
1342    ///
1343    /// let mut map = BiHashMap::new();
1344    /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
1345    ///     .unwrap();
1346    /// map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
1347    ///     .unwrap();
1348    ///
1349    /// assert!(map.contains_key2(&"foo"));
1350    /// assert!(map.contains_key2(&"bar"));
1351    /// assert!(!map.contains_key2(&"baz"));
1352    /// # }
1353    /// ```
1354    pub fn contains_key2<'a, Q>(&'a self, key2: &Q) -> bool
1355    where
1356        Q: Hash + Equivalent<T::K2<'a>> + ?Sized,
1357    {
1358        self.find2_index(key2).is_some()
1359    }
1360
1361    /// Gets a reference to the value associated with the given `key2`.
1362    ///
1363    /// # Examples
1364    ///
1365    /// ```
1366    /// # #[cfg(feature = "default-hasher")] {
1367    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
1368    ///
1369    /// #[derive(Debug, PartialEq, Eq)]
1370    /// struct Item {
1371    ///     id: u32,
1372    ///     name: String,
1373    ///     value: i32,
1374    /// }
1375    ///
1376    /// impl BiHashItem for Item {
1377    ///     type K1<'a> = u32;
1378    ///     type K2<'a> = &'a str;
1379    ///
1380    ///     fn key1(&self) -> Self::K1<'_> {
1381    ///         self.id
1382    ///     }
1383    ///     fn key2(&self) -> Self::K2<'_> {
1384    ///         &self.name
1385    ///     }
1386    ///     bi_upcast!();
1387    /// }
1388    ///
1389    /// let mut map = BiHashMap::new();
1390    /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
1391    ///     .unwrap();
1392    /// map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
1393    ///     .unwrap();
1394    ///
1395    /// assert_eq!(map.get2(&"foo").unwrap().value, 42);
1396    /// assert_eq!(map.get2(&"bar").unwrap().value, 99);
1397    /// assert!(map.get2(&"baz").is_none());
1398    /// # }
1399    /// ```
1400    pub fn get2<'a, Q>(&'a self, key2: &Q) -> Option<&'a T>
1401    where
1402        Q: Hash + Equivalent<T::K2<'a>> + ?Sized,
1403    {
1404        self.find2(key2)
1405    }
1406
1407    /// Gets a mutable reference to the value associated with the given `key2`.
1408    ///
1409    /// # Examples
1410    ///
1411    /// ```
1412    /// # #[cfg(feature = "default-hasher")] {
1413    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
1414    ///
1415    /// #[derive(Debug, PartialEq, Eq)]
1416    /// struct Item {
1417    ///     id: u32,
1418    ///     name: String,
1419    ///     value: i32,
1420    /// }
1421    ///
1422    /// impl BiHashItem for Item {
1423    ///     type K1<'a> = u32;
1424    ///     type K2<'a> = &'a str;
1425    ///
1426    ///     fn key1(&self) -> Self::K1<'_> {
1427    ///         self.id
1428    ///     }
1429    ///     fn key2(&self) -> Self::K2<'_> {
1430    ///         &self.name
1431    ///     }
1432    ///     bi_upcast!();
1433    /// }
1434    ///
1435    /// let mut map = BiHashMap::new();
1436    /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
1437    ///     .unwrap();
1438    ///
1439    /// if let Some(mut item_ref) = map.get2_mut(&"foo") {
1440    ///     item_ref.value = 100;
1441    /// }
1442    ///
1443    /// assert_eq!(map.get2(&"foo").unwrap().value, 100);
1444    /// # }
1445    /// ```
1446    pub fn get2_mut<'a, Q>(&'a mut self, key2: &Q) -> Option<RefMut<'a, T, S>>
1447    where
1448        Q: Hash + Equivalent<T::K2<'a>> + ?Sized,
1449    {
1450        let (dormant_map, index) = {
1451            let (map, dormant_map) = DormantMutRef::new(self);
1452            let index = map.find2_index(key2)?;
1453            (dormant_map, index)
1454        };
1455
1456        // SAFETY: `map` is not used after this point.
1457        let awakened_map = unsafe { dormant_map.awaken() };
1458        let item = &mut awakened_map.items[index];
1459        let state = awakened_map.tables.state.clone();
1460        let hashes =
1461            awakened_map.tables.make_hashes::<T>(&item.key1(), &item.key2());
1462        Some(RefMut::new(state, hashes, item))
1463    }
1464
1465    /// Removes an item from the map by its `key2`.
1466    ///
1467    /// # Examples
1468    ///
1469    /// ```
1470    /// # #[cfg(feature = "default-hasher")] {
1471    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
1472    ///
1473    /// #[derive(Debug, PartialEq, Eq)]
1474    /// struct Item {
1475    ///     id: u32,
1476    ///     name: String,
1477    ///     value: i32,
1478    /// }
1479    ///
1480    /// impl BiHashItem for Item {
1481    ///     type K1<'a> = u32;
1482    ///     type K2<'a> = &'a str;
1483    ///
1484    ///     fn key1(&self) -> Self::K1<'_> {
1485    ///         self.id
1486    ///     }
1487    ///     fn key2(&self) -> Self::K2<'_> {
1488    ///         &self.name
1489    ///     }
1490    ///     bi_upcast!();
1491    /// }
1492    ///
1493    /// let mut map = BiHashMap::new();
1494    /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
1495    ///     .unwrap();
1496    /// map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
1497    ///     .unwrap();
1498    ///
1499    /// let removed = map.remove2(&"foo");
1500    /// assert_eq!(removed.unwrap().value, 42);
1501    /// assert_eq!(map.len(), 1);
1502    /// assert!(map.get2(&"foo").is_none());
1503    /// assert!(map.remove2(&"baz").is_none());
1504    /// # }
1505    /// ```
1506    pub fn remove2<'a, Q>(&'a mut self, key2: &Q) -> Option<T>
1507    where
1508        Q: Hash + Equivalent<T::K2<'a>> + ?Sized,
1509    {
1510        let (dormant_map, remove_index) = {
1511            let (map, dormant_map) = DormantMutRef::new(self);
1512            let remove_index = map.find2_index(key2)?;
1513            (dormant_map, remove_index)
1514        };
1515
1516        // SAFETY: `map` is not used after this point.
1517        let awakened_map = unsafe { dormant_map.awaken() };
1518
1519        awakened_map.remove_by_index(remove_index)
1520    }
1521
1522    /// Retrieves an entry by its keys.
1523    ///
1524    /// Due to borrow checker limitations, this always accepts owned keys rather
1525    /// than a borrowed form of them.
1526    ///
1527    /// # Examples
1528    ///
1529    /// ```
1530    /// # #[cfg(feature = "default-hasher")] {
1531    /// use iddqd::{BiHashItem, BiHashMap, bi_hash_map, bi_upcast};
1532    ///
1533    /// #[derive(Debug, PartialEq, Eq)]
1534    /// struct Item {
1535    ///     id: u32,
1536    ///     name: String,
1537    ///     value: i32,
1538    /// }
1539    ///
1540    /// impl BiHashItem for Item {
1541    ///     type K1<'a> = u32;
1542    ///     type K2<'a> = &'a str;
1543    ///
1544    ///     fn key1(&self) -> Self::K1<'_> {
1545    ///         self.id
1546    ///     }
1547    ///     fn key2(&self) -> Self::K2<'_> {
1548    ///         &self.name
1549    ///     }
1550    ///     bi_upcast!();
1551    /// }
1552    ///
1553    /// let mut map = BiHashMap::new();
1554    /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
1555    ///     .unwrap();
1556    ///
1557    /// // Get existing entry
1558    /// match map.entry(1, "foo") {
1559    ///     bi_hash_map::Entry::Occupied(entry) => {
1560    ///         assert_eq!(entry.get().as_unique().unwrap().value, 42);
1561    ///     }
1562    ///     bi_hash_map::Entry::Vacant(_) => panic!("Should be occupied"),
1563    /// }
1564    ///
1565    /// // Try to get a non-existing entry
1566    /// match map.entry(2, "bar") {
1567    ///     bi_hash_map::Entry::Occupied(_) => panic!("Should be vacant"),
1568    ///     bi_hash_map::Entry::Vacant(entry) => {
1569    ///         entry.insert(Item { id: 2, name: "bar".to_string(), value: 99 });
1570    ///     }
1571    /// }
1572    ///
1573    /// assert_eq!(map.len(), 2);
1574    /// # }
1575    /// ```
1576    pub fn entry<'a>(
1577        &'a mut self,
1578        key1: T::K1<'_>,
1579        key2: T::K2<'_>,
1580    ) -> Entry<'a, T, S, A> {
1581        // Why does this always take owned keys? Well, it would seem like we
1582        // should be able to pass in any Q1 and Q2 that are equivalent. That
1583        // results in *this* code compiling fine, but callers have trouble using
1584        // it because the borrow checker believes the keys are borrowed for the
1585        // full 'a rather than a shorter lifetime.
1586        //
1587        // By accepting owned keys, we can use the upcast functions to convert
1588        // them to a shorter lifetime (so this function accepts T::K1<'_> rather
1589        // than T::K1<'a>).
1590        //
1591        // Really, the solution here is to allow GATs to require covariant
1592        // parameters. If that were allowed, the borrow checker should be able
1593        // to figure out that keys don't need to be borrowed for the full 'a,
1594        // just for some shorter lifetime.
1595        let (map, dormant_map) = DormantMutRef::new(self);
1596        let key1 = T::upcast_key1(key1);
1597        let key2 = T::upcast_key2(key2);
1598        let (index1, index2) = {
1599            // index1 and index2 are explicitly typed to show that it has a
1600            // trivial Drop impl that doesn't capture anything from map.
1601            let index1: Option<usize> = map.tables.k1_to_item.find_index(
1602                &map.tables.state,
1603                &key1,
1604                |index| map.items[index].key1(),
1605            );
1606            let index2: Option<usize> = map.tables.k2_to_item.find_index(
1607                &map.tables.state,
1608                &key2,
1609                |index| map.items[index].key2(),
1610            );
1611            (index1, index2)
1612        };
1613
1614        match (index1, index2) {
1615            (Some(index1), Some(index2)) if index1 == index2 => {
1616                // The item is already in the map.
1617                drop(key1);
1618                Entry::Occupied(
1619                    // SAFETY: `map` is not used after this point.
1620                    unsafe {
1621                        OccupiedEntry::new(
1622                            dormant_map,
1623                            EntryIndexes::Unique(index1),
1624                        )
1625                    },
1626                )
1627            }
1628            (None, None) => {
1629                let hashes = map.tables.make_hashes::<T>(&key1, &key2);
1630                Entry::Vacant(
1631                    // SAFETY: `map` is not used after this point.
1632                    unsafe { VacantEntry::new(dormant_map, hashes) },
1633                )
1634            }
1635            (index1, index2) => Entry::Occupied(
1636                // SAFETY: `map` is not used after this point.
1637                unsafe {
1638                    OccupiedEntry::new(
1639                        dormant_map,
1640                        EntryIndexes::NonUnique { index1, index2 },
1641                    )
1642                },
1643            ),
1644        }
1645    }
1646
1647    /// Retains only the elements specified by the predicate.
1648    ///
1649    /// In other words, remove all items `T` for which `f(RefMut<T>)` returns
1650    /// false. The elements are visited in an arbitrary order.
1651    ///
1652    /// # Examples
1653    ///
1654    /// ```
1655    /// # #[cfg(feature = "default-hasher")] {
1656    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
1657    ///
1658    /// #[derive(Debug, PartialEq, Eq, Hash)]
1659    /// struct Item {
1660    ///     id: u32,
1661    ///     name: String,
1662    ///     value: u32,
1663    /// }
1664    ///
1665    /// impl BiHashItem for Item {
1666    ///     type K1<'a> = u32;
1667    ///     type K2<'a> = &'a str;
1668    ///
1669    ///     fn key1(&self) -> Self::K1<'_> {
1670    ///         self.id
1671    ///     }
1672    ///     fn key2(&self) -> Self::K2<'_> {
1673    ///         &self.name
1674    ///     }
1675    ///
1676    ///     bi_upcast!();
1677    /// }
1678    ///
1679    /// let mut map = BiHashMap::new();
1680    /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
1681    ///     .unwrap();
1682    /// map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 20 })
1683    ///     .unwrap();
1684    /// map.insert_unique(Item { id: 3, name: "baz".to_string(), value: 99 })
1685    ///     .unwrap();
1686    ///
1687    /// // Retain only items where value is greater than 30
1688    /// map.retain(|item| item.value > 30);
1689    ///
1690    /// assert_eq!(map.len(), 2);
1691    /// assert_eq!(map.get1(&1).unwrap().value, 42);
1692    /// assert_eq!(map.get1(&3).unwrap().value, 99);
1693    /// assert!(map.get1(&2).is_none());
1694    /// # }
1695    /// ```
1696    pub fn retain<'a, F>(&'a mut self, mut f: F)
1697    where
1698        F: FnMut(RefMut<'a, T, S>) -> bool,
1699    {
1700        let hash_state = self.tables.state.clone();
1701        let (_, mut dormant_items) = DormantMutRef::new(&mut self.items);
1702
1703        self.tables.k1_to_item.retain(|index| {
1704            let (item, dormant_items) = {
1705                // SAFETY: All uses of `items` ended in the previous iteration.
1706                let items = unsafe { dormant_items.reborrow() };
1707                let (items, dormant_items) = DormantMutRef::new(items);
1708                let item: &'a mut T = items
1709                    .get_mut(index)
1710                    .expect("all indexes are present in self.items");
1711                (item, dormant_items)
1712            };
1713
1714            let (hashes, dormant_item) = {
1715                let (item, dormant_item): (&'a mut T, _) =
1716                    DormantMutRef::new(item);
1717                // Use T::k1(item) rather than item.key() to force the key
1718                // trait function to be called for T rather than &mut T.
1719                let key1 = T::key1(item);
1720                let key2 = T::key2(item);
1721                let hash1 = hash_state.hash_one(key1);
1722                let hash2 = hash_state.hash_one(key2);
1723                ([MapHash::new(hash1), MapHash::new(hash2)], dormant_item)
1724            };
1725
1726            // SAFETY: The original items is no longer used after the first
1727            // block above.
1728            let items = unsafe { dormant_items.awaken() };
1729            // SAFETY: The original item is no longer used after the second
1730            // block above.
1731            let item = unsafe { dormant_item.awaken() };
1732
1733            let hash2 = hashes[1].hash();
1734
1735            let ref_mut = RefMut::new(hash_state.clone(), hashes, item);
1736            if f(ref_mut) {
1737                true
1738            } else {
1739                items.remove(index);
1740                let k2_entry = self
1741                    .tables
1742                    .k2_to_item
1743                    .find_entry_by_hash(hash2, |map2_index| {
1744                        map2_index == index
1745                    });
1746                match k2_entry {
1747                    Ok(entry) => {
1748                        entry.remove();
1749                    }
1750                    Err(_) => {
1751                        // This happening means there's an inconsistency between
1752                        // the maps.
1753                        panic!(
1754                            "inconsistency between k1_to_item and k2_to_item"
1755                        );
1756                    }
1757                }
1758
1759                false
1760            }
1761        });
1762    }
1763
1764    fn find1<'a, Q>(&'a self, k: &Q) -> Option<&'a T>
1765    where
1766        Q: Hash + Equivalent<T::K1<'a>> + ?Sized,
1767    {
1768        self.find1_index(k).map(|ix| &self.items[ix])
1769    }
1770
1771    fn find1_index<'a, Q>(&'a self, k: &Q) -> Option<usize>
1772    where
1773        Q: Hash + Equivalent<T::K1<'a>> + ?Sized,
1774    {
1775        self.tables
1776            .k1_to_item
1777            .find_index(&self.tables.state, k, |index| self.items[index].key1())
1778    }
1779
1780    fn find2<'a, Q>(&'a self, k: &Q) -> Option<&'a T>
1781    where
1782        Q: Hash + Equivalent<T::K2<'a>> + ?Sized,
1783    {
1784        self.find2_index(k).map(|ix| &self.items[ix])
1785    }
1786
1787    fn find2_index<'a, Q>(&'a self, k: &Q) -> Option<usize>
1788    where
1789        Q: Hash + Equivalent<T::K2<'a>> + ?Sized,
1790    {
1791        self.tables
1792            .k2_to_item
1793            .find_index(&self.tables.state, k, |index| self.items[index].key2())
1794    }
1795
1796    pub(super) fn get_by_entry_index(
1797        &self,
1798        indexes: EntryIndexes,
1799    ) -> OccupiedEntryRef<'_, T> {
1800        match indexes {
1801            EntryIndexes::Unique(index) => OccupiedEntryRef::Unique(
1802                self.items.get(index).expect("index is valid"),
1803            ),
1804            EntryIndexes::NonUnique { index1, index2 } => {
1805                let by_key1 = index1
1806                    .map(|k| self.items.get(k).expect("key1 index is valid"));
1807                let by_key2 = index2
1808                    .map(|k| self.items.get(k).expect("key2 index is valid"));
1809                OccupiedEntryRef::NonUnique { by_key1, by_key2 }
1810            }
1811        }
1812    }
1813
1814    pub(super) fn get_by_entry_index_mut(
1815        &mut self,
1816        indexes: EntryIndexes,
1817    ) -> OccupiedEntryMut<'_, T, S> {
1818        match indexes.disjoint_keys() {
1819            DisjointKeys::Unique(index) => {
1820                let item = self.items.get_mut(index).expect("index is valid");
1821                let state = self.tables.state.clone();
1822                let hashes =
1823                    self.tables.make_hashes::<T>(&item.key1(), &item.key2());
1824                OccupiedEntryMut::Unique(RefMut::new(state, hashes, item))
1825            }
1826            DisjointKeys::Key1(index1) => {
1827                let item =
1828                    self.items.get_mut(index1).expect("key1 index is valid");
1829                let state = self.tables.state.clone();
1830                let hashes =
1831                    self.tables.make_hashes::<T>(&item.key1(), &item.key2());
1832                OccupiedEntryMut::NonUnique {
1833                    by_key1: Some(RefMut::new(state, hashes, item)),
1834                    by_key2: None,
1835                }
1836            }
1837            DisjointKeys::Key2(index2) => {
1838                let item =
1839                    self.items.get_mut(index2).expect("key2 index is valid");
1840                let state = self.tables.state.clone();
1841                let hashes =
1842                    self.tables.make_hashes::<T>(&item.key1(), &item.key2());
1843                OccupiedEntryMut::NonUnique {
1844                    by_key1: None,
1845                    by_key2: Some(RefMut::new(state, hashes, item)),
1846                }
1847            }
1848            DisjointKeys::Key12(indexes) => {
1849                let state = self.tables.state.clone();
1850                let mut items = self.items.get_disjoint_mut(indexes);
1851                let item1 = items[0].take().expect("key1 index is valid");
1852                let item2 = items[1].take().expect("key2 index is valid");
1853                let hashes1 =
1854                    self.tables.make_hashes::<T>(&item1.key1(), &item1.key2());
1855                let hashes2 =
1856                    self.tables.make_hashes::<T>(&item2.key1(), &item2.key2());
1857
1858                OccupiedEntryMut::NonUnique {
1859                    by_key1: Some(RefMut::new(state.clone(), hashes1, item1)),
1860                    by_key2: Some(RefMut::new(state, hashes2, item2)),
1861                }
1862            }
1863        }
1864    }
1865
1866    pub(super) fn get_by_index_mut(
1867        &mut self,
1868        index: usize,
1869    ) -> Option<RefMut<'_, T, S>> {
1870        let borrowed = self.items.get_mut(index)?;
1871        let state = self.tables.state.clone();
1872        let hashes =
1873            self.tables.make_hashes::<T>(&borrowed.key1(), &borrowed.key2());
1874        let item = &mut self.items[index];
1875        Some(RefMut::new(state, hashes, item))
1876    }
1877
1878    pub(super) fn insert_unique_impl(
1879        &mut self,
1880        value: T,
1881    ) -> Result<usize, DuplicateItem<T, &T>> {
1882        let mut duplicates = BTreeSet::new();
1883
1884        // Check for duplicates *before* inserting the new item, because we
1885        // don't want to partially insert the new item and then have to roll
1886        // back.
1887        let state = &self.tables.state;
1888        let (e1, e2) = {
1889            let k1 = value.key1();
1890            let k2 = value.key2();
1891
1892            let e1 = detect_dup_or_insert(
1893                self.tables
1894                    .k1_to_item
1895                    .entry(state, k1, |index| self.items[index].key1()),
1896                &mut duplicates,
1897            );
1898            let e2 = detect_dup_or_insert(
1899                self.tables
1900                    .k2_to_item
1901                    .entry(state, k2, |index| self.items[index].key2()),
1902                &mut duplicates,
1903            );
1904            (e1, e2)
1905        };
1906
1907        if !duplicates.is_empty() {
1908            return Err(DuplicateItem::__internal_new(
1909                value,
1910                duplicates.iter().map(|ix| &self.items[*ix]).collect(),
1911            ));
1912        }
1913
1914        let next_index = self.items.insert_at_next_index(value);
1915        // e1 and e2 are all Some because if they were None, duplicates
1916        // would be non-empty, and we'd have bailed out earlier.
1917        e1.unwrap().insert(next_index);
1918        e2.unwrap().insert(next_index);
1919
1920        Ok(next_index)
1921    }
1922
1923    pub(super) fn remove_by_entry_index(
1924        &mut self,
1925        indexes: EntryIndexes,
1926    ) -> Vec<T> {
1927        match indexes {
1928            EntryIndexes::Unique(index) => {
1929                // Since all keys match, we can simply replace the item.
1930                let old_item =
1931                    self.remove_by_index(index).expect("index is valid");
1932                vec![old_item]
1933            }
1934            EntryIndexes::NonUnique { index1, index2 } => {
1935                let mut old_items = Vec::new();
1936                if let Some(index1) = index1 {
1937                    old_items.push(
1938                        self.remove_by_index(index1).expect("index1 is valid"),
1939                    );
1940                }
1941                if let Some(index2) = index2 {
1942                    old_items.push(
1943                        self.remove_by_index(index2).expect("index2 is valid"),
1944                    );
1945                }
1946
1947                old_items
1948            }
1949        }
1950    }
1951
1952    pub(super) fn remove_by_index(&mut self, remove_index: usize) -> Option<T> {
1953        let value = self.items.remove(remove_index)?;
1954
1955        // Remove the value from the tables.
1956        let state = &self.tables.state;
1957        let Ok(item1) =
1958            self.tables.k1_to_item.find_entry(state, &value.key1(), |index| {
1959                if index == remove_index {
1960                    value.key1()
1961                } else {
1962                    self.items[index].key1()
1963                }
1964            })
1965        else {
1966            // The item was not found.
1967            panic!("remove_index {remove_index} not found in k1_to_item");
1968        };
1969        let Ok(item2) =
1970            self.tables.k2_to_item.find_entry(state, &value.key2(), |index| {
1971                if index == remove_index {
1972                    value.key2()
1973                } else {
1974                    self.items[index].key2()
1975                }
1976            })
1977        else {
1978            // The item was not found.
1979            panic!("remove_index {remove_index} not found in k2_to_item")
1980        };
1981
1982        item1.remove();
1983        item2.remove();
1984
1985        Some(value)
1986    }
1987
1988    pub(super) fn replace_at_indexes(
1989        &mut self,
1990        indexes: EntryIndexes,
1991        value: T,
1992    ) -> (usize, Vec<T>) {
1993        match indexes {
1994            EntryIndexes::Unique(index) => {
1995                let old_item = &self.items[index];
1996                if old_item.key1() != value.key1() {
1997                    panic!("key1 mismatch");
1998                }
1999                if old_item.key2() != value.key2() {
2000                    panic!("key2 mismatch");
2001                }
2002
2003                // Since all keys match, we can simply replace the item.
2004                let old_item = self.items.replace(index, value);
2005                (index, vec![old_item])
2006            }
2007            EntryIndexes::NonUnique { index1, index2 } => {
2008                let mut old_items = Vec::new();
2009                if let Some(index1) = index1 {
2010                    let old_item = &self.items[index1];
2011                    if old_item.key1() != value.key1() {
2012                        panic!("key1 mismatch");
2013                    }
2014                    old_items.push(self.remove_by_index(index1).unwrap());
2015                }
2016                if let Some(index2) = index2 {
2017                    let old_item = &self.items[index2];
2018                    if old_item.key2() != value.key2() {
2019                        panic!("key2 mismatch");
2020                    }
2021                    old_items.push(self.remove_by_index(index2).unwrap());
2022                }
2023
2024                // Insert the new item.
2025                let Ok(next_index) = self.insert_unique_impl(value) else {
2026                    unreachable!(
2027                        "insert_unique cannot fail after removing duplicates"
2028                    );
2029                };
2030                (next_index, old_items)
2031            }
2032        }
2033    }
2034}
2035
2036impl<'a, T, S, A> fmt::Debug for BiHashMap<T, S, A>
2037where
2038    T: BiHashItem + fmt::Debug,
2039    T::K1<'a>: fmt::Debug,
2040    T::K2<'a>: fmt::Debug,
2041    T: 'a,
2042    A: Allocator,
2043{
2044    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2045        let mut map = f.debug_map();
2046        for item in self.items.values() {
2047            let key: KeyMap<'_, T> =
2048                KeyMap { key1: item.key1(), key2: item.key2() };
2049
2050            // SAFETY:
2051            //
2052            // * Lifetime extension: for a type T and two lifetime params 'a and
2053            //   'b, T<'a> and T<'b> aren't guaranteed to have the same layout,
2054            //   but (a) that is true today and (b) it would be shocking and
2055            //   break half the Rust ecosystem if that were to change in the
2056            //   future.
2057            // * We only use key within the scope of this block before immediately
2058            //   dropping it. In particular, map.entry calls key.fmt() without
2059            //   holding a reference to it.
2060            let key: KeyMap<'a, T> = unsafe {
2061                core::mem::transmute::<KeyMap<'_, T>, KeyMap<'a, T>>(key)
2062            };
2063
2064            map.entry(&key as &dyn fmt::Debug, item);
2065        }
2066        map.finish()
2067    }
2068}
2069
2070struct KeyMap<'a, T: BiHashItem + 'a> {
2071    key1: T::K1<'a>,
2072    key2: T::K2<'a>,
2073}
2074
2075impl<'a, T: BiHashItem + 'a> fmt::Debug for KeyMap<'a, T>
2076where
2077    T::K1<'a>: fmt::Debug,
2078    T::K2<'a>: fmt::Debug,
2079{
2080    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2081        // We don't want to show key1 and key2 as a tuple since it's
2082        // misleading (suggests maps of tuples). The best we can do
2083        // instead is to show "{k1: "abc", k2: "xyz"}"
2084        f.debug_map()
2085            .entry(&StrDisplayAsDebug("k1"), &self.key1)
2086            .entry(&StrDisplayAsDebug("k2"), &self.key2)
2087            .finish()
2088    }
2089}
2090
2091/// The `PartialEq` implementation for `BiHashMap` checks that both maps have
2092/// the same items, regardless of insertion order.
2093///
2094/// # Examples
2095///
2096/// ```
2097/// # #[cfg(feature = "default-hasher")] {
2098/// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
2099///
2100/// #[derive(Debug, PartialEq, Eq)]
2101/// struct Item {
2102///     id: u32,
2103///     name: String,
2104///     value: i32,
2105/// }
2106///
2107/// impl BiHashItem for Item {
2108///     type K1<'a> = u32;
2109///     type K2<'a> = &'a str;
2110///
2111///     fn key1(&self) -> Self::K1<'_> {
2112///         self.id
2113///     }
2114///     fn key2(&self) -> Self::K2<'_> {
2115///         &self.name
2116///     }
2117///     bi_upcast!();
2118/// }
2119///
2120/// let mut map1 = BiHashMap::new();
2121/// map1.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
2122///     .unwrap();
2123/// map1.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
2124///     .unwrap();
2125///
2126/// let mut map2 = BiHashMap::new();
2127/// map2.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
2128///     .unwrap();
2129/// map2.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
2130///     .unwrap();
2131///
2132/// // Maps are equal even if items were inserted in different order
2133/// assert_eq!(map1, map2);
2134///
2135/// map2.insert_unique(Item { id: 3, name: "baz".to_string(), value: 200 })
2136///     .unwrap();
2137/// assert_ne!(map1, map2);
2138/// # }
2139/// ```
2140impl<T: BiHashItem + PartialEq, S: Clone + BuildHasher, A: Allocator> PartialEq
2141    for BiHashMap<T, S, A>
2142{
2143    fn eq(&self, other: &Self) -> bool {
2144        // Implementing PartialEq for BiHashMap is tricky because BiHashMap is
2145        // not semantically like an IndexMap: two maps are equivalent even if
2146        // their items are in a different order. In other words, any permutation
2147        // of items is equivalent.
2148        //
2149        // We also can't sort the items because they're not necessarily Ord.
2150        //
2151        // So we write a custom equality check that checks that each key in one
2152        // map points to the same item as in the other map.
2153
2154        if self.items.len() != other.items.len() {
2155            return false;
2156        }
2157
2158        // Walk over all the items in the first map and check that they point to
2159        // the same item in the second map.
2160        for item in self.items.values() {
2161            let k1 = item.key1();
2162            let k2 = item.key2();
2163
2164            // Check that the indexes are the same in the other map.
2165            let Some(other_ix1) = other.find1_index(&k1) else {
2166                return false;
2167            };
2168            let Some(other_ix2) = other.find2_index(&k2) else {
2169                return false;
2170            };
2171
2172            if other_ix1 != other_ix2 {
2173                // All the keys were present but they didn't point to the same
2174                // item.
2175                return false;
2176            }
2177
2178            // Check that the other map's item is the same as this map's
2179            // item. (This is what we use the `PartialEq` bound on T for.)
2180            //
2181            // Because we've checked that other_ix1 and other_ix2 are
2182            // Some, we know that it is valid and points to the expected item.
2183            let other_item = &other.items[other_ix1];
2184            if item != other_item {
2185                return false;
2186            }
2187        }
2188
2189        true
2190    }
2191}
2192
2193// The Eq bound on T ensures that the BiHashMap forms an equivalence class.
2194impl<T: BiHashItem + Eq, S: Clone + BuildHasher, A: Allocator> Eq
2195    for BiHashMap<T, S, A>
2196{
2197}
2198
2199fn detect_dup_or_insert<'a, A: Allocator>(
2200    item: hash_table::Entry<'a, usize, AllocWrapper<A>>,
2201    duplicates: &mut BTreeSet<usize>,
2202) -> Option<hash_table::VacantEntry<'a, usize, AllocWrapper<A>>> {
2203    match item {
2204        hash_table::Entry::Vacant(slot) => Some(slot),
2205        hash_table::Entry::Occupied(slot) => {
2206            duplicates.insert(*slot.get());
2207            None
2208        }
2209    }
2210}
2211
2212/// The `Extend` implementation overwrites duplicates. In the future, there will
2213/// also be an `extend_unique` method that will return an error.
2214///
2215/// # Examples
2216///
2217/// ```
2218/// # #[cfg(feature = "default-hasher")] {
2219/// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
2220///
2221/// #[derive(Debug, PartialEq, Eq)]
2222/// struct Item {
2223///     id: u32,
2224///     name: String,
2225///     value: i32,
2226/// }
2227///
2228/// impl BiHashItem for Item {
2229///     type K1<'a> = u32;
2230///     type K2<'a> = &'a str;
2231///
2232///     fn key1(&self) -> Self::K1<'_> {
2233///         self.id
2234///     }
2235///     fn key2(&self) -> Self::K2<'_> {
2236///         &self.name
2237///     }
2238///     bi_upcast!();
2239/// }
2240///
2241/// let mut map = BiHashMap::new();
2242/// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 }).unwrap();
2243///
2244/// let new_items = vec![
2245///     Item { id: 2, name: "bar".to_string(), value: 99 },
2246///     Item { id: 1, name: "baz".to_string(), value: 100 }, // overwrites existing
2247/// ];
2248///
2249/// map.extend(new_items);
2250/// assert_eq!(map.len(), 2);
2251/// assert_eq!(map.get1(&1).unwrap().name, "baz"); // overwritten
2252/// assert_eq!(map.get1(&1).unwrap().value, 100);
2253/// # }
2254/// ```
2255impl<T: BiHashItem, S: Clone + BuildHasher, A: Allocator> Extend<T>
2256    for BiHashMap<T, S, A>
2257{
2258    fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
2259        for item in iter {
2260            self.insert_overwrite(item);
2261        }
2262    }
2263}
2264
2265impl<'a, T: BiHashItem, S: Clone + BuildHasher, A: Allocator> IntoIterator
2266    for &'a BiHashMap<T, S, A>
2267{
2268    type Item = &'a T;
2269    type IntoIter = Iter<'a, T>;
2270
2271    #[inline]
2272    fn into_iter(self) -> Self::IntoIter {
2273        self.iter()
2274    }
2275}
2276
2277impl<'a, T: BiHashItem, S: Clone + BuildHasher, A: Allocator> IntoIterator
2278    for &'a mut BiHashMap<T, S, A>
2279{
2280    type Item = RefMut<'a, T, S>;
2281    type IntoIter = IterMut<'a, T, S, A>;
2282
2283    #[inline]
2284    fn into_iter(self) -> Self::IntoIter {
2285        self.iter_mut()
2286    }
2287}
2288
2289impl<T: BiHashItem, S: Clone + BuildHasher, A: Allocator> IntoIterator
2290    for BiHashMap<T, S, A>
2291{
2292    type Item = T;
2293    type IntoIter = IntoIter<T, A>;
2294
2295    #[inline]
2296    fn into_iter(self) -> Self::IntoIter {
2297        IntoIter::new(self.items)
2298    }
2299}
2300
2301/// The `FromIterator` implementation for `BiHashMap` overwrites duplicate
2302/// items.
2303///
2304/// # Examples
2305///
2306/// ```
2307/// # #[cfg(feature = "default-hasher")] {
2308/// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
2309///
2310/// #[derive(Debug, PartialEq, Eq)]
2311/// struct Item {
2312///     id: u32,
2313///     name: String,
2314///     value: i32,
2315/// }
2316///
2317/// impl BiHashItem for Item {
2318///     type K1<'a> = u32;
2319///     type K2<'a> = &'a str;
2320///
2321///     fn key1(&self) -> Self::K1<'_> {
2322///         self.id
2323///     }
2324///     fn key2(&self) -> Self::K2<'_> {
2325///         &self.name
2326///     }
2327///     bi_upcast!();
2328/// }
2329///
2330/// let items = vec![
2331///     Item { id: 1, name: "foo".to_string(), value: 42 },
2332///     Item { id: 2, name: "bar".to_string(), value: 99 },
2333///     Item { id: 1, name: "baz".to_string(), value: 100 }, // overwrites first item
2334/// ];
2335///
2336/// let map: BiHashMap<Item> = items.into_iter().collect();
2337/// assert_eq!(map.len(), 2);
2338/// assert_eq!(map.get1(&1).unwrap().name, "baz"); // overwritten
2339/// assert_eq!(map.get1(&1).unwrap().value, 100);
2340/// assert_eq!(map.get1(&2).unwrap().value, 99);
2341/// # }
2342/// ```
2343impl<T: BiHashItem, S: Clone + BuildHasher + Default, A: Default + Allocator>
2344    FromIterator<T> for BiHashMap<T, S, A>
2345{
2346    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
2347        let mut map = BiHashMap::default();
2348        for item in iter {
2349            map.insert_overwrite(item);
2350        }
2351        map
2352    }
2353}