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    },
18};
19use alloc::{collections::BTreeSet, vec::Vec};
20use core::{
21    fmt,
22    hash::{BuildHasher, Hash},
23};
24use equivalent::Equivalent;
25use hashbrown::hash_table;
26
27/// A 1:1 (bijective) map for two keys and a value.
28///
29/// The storage mechanism is a fast hash table of integer indexes to items, with
30/// these indexes stored in two hash tables. This allows for efficient lookups
31/// by either of the two keys and prevents duplicates.
32///
33/// # Examples
34///
35/// ```
36/// # #[cfg(feature = "default-hasher")] {
37/// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
38///
39/// // Define a struct with two keys and a value.
40/// #[derive(Debug, PartialEq, Eq)]
41/// struct MyItem {
42///     id: u32,
43///     name: &'static str,
44///     value: i32,
45/// }
46///
47/// // Implement BiHashItem for the struct.
48/// impl BiHashItem for MyItem {
49///     type K1<'a> = u32;
50///     type K2<'a> = &'a str;
51///
52///     fn key1(&self) -> Self::K1<'_> {
53///         self.id
54///     }
55///     fn key2(&self) -> Self::K2<'_> {
56///         self.name
57///     }
58///
59///     bi_upcast!();
60/// }
61///
62/// // Create a new BiHashMap and insert items.
63/// let mut map = BiHashMap::new();
64/// map.insert_unique(MyItem { id: 1, name: "foo", value: 42 }).unwrap();
65/// map.insert_unique(MyItem { id: 2, name: "bar", value: 99 }).unwrap();
66///
67/// // Look up by the first key.
68/// assert_eq!(map.get1(&1).unwrap().value, 42);
69/// assert_eq!(map.get1(&2).unwrap().value, 99);
70/// assert!(map.get1(&3).is_none());
71///
72/// // Look up by the second key.
73/// assert_eq!(map.get2(&"foo").unwrap().value, 42);
74/// assert_eq!(map.get2(&"bar").unwrap().value, 99);
75/// assert!(map.get2(&"baz").is_none());
76/// # }
77/// ```
78#[derive(Clone)]
79pub struct BiHashMap<T, S = DefaultHashBuilder, A: Allocator = Global> {
80    pub(super) items: ItemSet<T, A>,
81    // Invariant: the values (usize) in these tables are valid indexes into
82    // `items`, and are a 1:1 mapping.
83    tables: BiHashMapTables<S, A>,
84}
85
86impl<T: BiHashItem, S: Default, A: Allocator + Default> Default
87    for BiHashMap<T, S, A>
88{
89    fn default() -> Self {
90        Self {
91            items: ItemSet::with_capacity_in(0, A::default()),
92            tables: BiHashMapTables::default(),
93        }
94    }
95}
96
97#[cfg(feature = "default-hasher")]
98impl<T: BiHashItem> BiHashMap<T> {
99    /// Creates a new, empty `BiHashMap`.
100    ///
101    /// # Examples
102    ///
103    /// ```
104    /// # #[cfg(feature = "default-hasher")] {
105    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
106    ///
107    /// #[derive(Debug, PartialEq, Eq)]
108    /// struct Item {
109    ///     id: u32,
110    ///     name: String,
111    ///     value: i32,
112    /// }
113    ///
114    /// impl BiHashItem for Item {
115    ///     type K1<'a> = u32;
116    ///     type K2<'a> = &'a str;
117    ///
118    ///     fn key1(&self) -> Self::K1<'_> {
119    ///         self.id
120    ///     }
121    ///     fn key2(&self) -> Self::K2<'_> {
122    ///         &self.name
123    ///     }
124    ///     bi_upcast!();
125    /// }
126    ///
127    /// let map: BiHashMap<Item> = BiHashMap::new();
128    /// assert!(map.is_empty());
129    /// assert_eq!(map.len(), 0);
130    /// # }
131    /// ```
132    #[inline]
133    pub fn new() -> Self {
134        Self { items: ItemSet::default(), tables: BiHashMapTables::default() }
135    }
136
137    /// Creates a new `BiHashMap` with the given capacity.
138    ///
139    /// # Examples
140    ///
141    /// ```
142    /// # #[cfg(feature = "default-hasher")] {
143    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
144    ///
145    /// #[derive(Debug, PartialEq, Eq)]
146    /// struct Item {
147    ///     id: u32,
148    ///     name: String,
149    ///     value: i32,
150    /// }
151    ///
152    /// impl BiHashItem for Item {
153    ///     type K1<'a> = u32;
154    ///     type K2<'a> = &'a str;
155    ///
156    ///     fn key1(&self) -> Self::K1<'_> {
157    ///         self.id
158    ///     }
159    ///     fn key2(&self) -> Self::K2<'_> {
160    ///         &self.name
161    ///     }
162    ///     bi_upcast!();
163    /// }
164    ///
165    /// let map: BiHashMap<Item> = BiHashMap::with_capacity(10);
166    /// assert!(map.capacity() >= 10);
167    /// assert!(map.is_empty());
168    /// # }
169    /// ```
170    pub fn with_capacity(capacity: usize) -> Self {
171        Self {
172            items: ItemSet::with_capacity_in(capacity, global_alloc()),
173            tables: BiHashMapTables::with_capacity_and_hasher_in(
174                capacity,
175                DefaultHashBuilder::default(),
176                global_alloc(),
177            ),
178        }
179    }
180}
181
182impl<T: BiHashItem, S: Clone + BuildHasher> BiHashMap<T, S> {
183    /// Creates a new `BiHashMap` with the given hasher.
184    ///
185    /// # Examples
186    ///
187    /// ```
188    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
189    /// use std::collections::hash_map::RandomState;
190    ///
191    /// #[derive(Debug, PartialEq, Eq)]
192    /// struct Item {
193    ///     id: u32,
194    ///     name: String,
195    ///     value: i32,
196    /// }
197    ///
198    /// impl BiHashItem for Item {
199    ///     type K1<'a> = u32;
200    ///     type K2<'a> = &'a str;
201    ///
202    ///     fn key1(&self) -> Self::K1<'_> {
203    ///         self.id
204    ///     }
205    ///     fn key2(&self) -> Self::K2<'_> {
206    ///         &self.name
207    ///     }
208    ///     bi_upcast!();
209    /// }
210    ///
211    /// let hasher = RandomState::new();
212    /// let map: BiHashMap<Item, RandomState> = BiHashMap::with_hasher(hasher);
213    /// assert!(map.is_empty());
214    /// ```
215    pub fn with_hasher(hasher: S) -> Self {
216        Self {
217            items: ItemSet::default(),
218            tables: BiHashMapTables::with_capacity_and_hasher_in(
219                0,
220                hasher,
221                global_alloc(),
222            ),
223        }
224    }
225
226    /// Creates a new `BiHashMap` with the given capacity and hasher.
227    ///
228    /// # Examples
229    ///
230    /// ```
231    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
232    /// use std::collections::hash_map::RandomState;
233    ///
234    /// #[derive(Debug, PartialEq, Eq)]
235    /// struct Item {
236    ///     id: u32,
237    ///     name: String,
238    ///     value: i32,
239    /// }
240    ///
241    /// impl BiHashItem for Item {
242    ///     type K1<'a> = u32;
243    ///     type K2<'a> = &'a str;
244    ///
245    ///     fn key1(&self) -> Self::K1<'_> {
246    ///         self.id
247    ///     }
248    ///     fn key2(&self) -> Self::K2<'_> {
249    ///         &self.name
250    ///     }
251    ///     bi_upcast!();
252    /// }
253    ///
254    /// let hasher = RandomState::new();
255    /// let map: BiHashMap<Item, _> =
256    ///     BiHashMap::with_capacity_and_hasher(10, hasher);
257    /// assert!(map.capacity() >= 10);
258    /// assert!(map.is_empty());
259    /// ```
260    pub fn with_capacity_and_hasher(capacity: usize, hasher: S) -> Self {
261        Self {
262            items: ItemSet::with_capacity_in(capacity, global_alloc()),
263            tables: BiHashMapTables::with_capacity_and_hasher_in(
264                capacity,
265                hasher,
266                global_alloc(),
267            ),
268        }
269    }
270}
271
272#[cfg(feature = "default-hasher")]
273impl<T: BiHashItem, A: Clone + Allocator> BiHashMap<T, DefaultHashBuilder, A> {
274    /// Creates a new empty `BiHashMap` using the given allocator.
275    ///
276    /// Requires the `allocator-api2` feature to be enabled.
277    ///
278    /// # Examples
279    ///
280    /// Using the [`bumpalo`](https://docs.rs/bumpalo) allocator:
281    ///
282    /// ```
283    /// # #[cfg(all(feature = "default-hasher", feature = "allocator-api2"))] {
284    /// use iddqd::{BiHashMap, BiHashItem, bi_upcast};
285    /// # use iddqd_test_utils::bumpalo;
286    ///
287    /// #[derive(Debug, PartialEq, Eq)]
288    /// struct Item {
289    ///     id: u32,
290    ///     name: String,
291    ///     value: i32,
292    /// }
293    ///
294    /// impl BiHashItem for Item {
295    ///     type K1<'a> = u32;
296    ///     type K2<'a> = &'a str;
297    ///
298    ///     fn key1(&self) -> Self::K1<'_> {
299    ///         self.id
300    ///     }
301    ///     fn key2(&self) -> Self::K2<'_> {
302    ///         &self.name
303    ///     }
304    ///     bi_upcast!();
305    /// }
306    ///
307    /// // Define a new allocator.
308    /// let bump = bumpalo::Bump::new();
309    /// // Create a new BiHashMap using the allocator.
310    /// let map: BiHashMap<Item, _, &bumpalo::Bump> = BiHashMap::new_in(&bump);
311    /// assert!(map.is_empty());
312    /// # }
313    /// ```
314    pub fn new_in(alloc: A) -> Self {
315        Self {
316            items: ItemSet::with_capacity_in(0, alloc.clone()),
317            tables: BiHashMapTables::with_capacity_and_hasher_in(
318                0,
319                DefaultHashBuilder::default(),
320                alloc,
321            ),
322        }
323    }
324
325    /// Creates an empty `BiHashMap` with the specified capacity using the given
326    /// allocator.
327    ///
328    /// Requires the `allocator-api2` feature to be enabled.
329    ///
330    /// # Examples
331    ///
332    /// Using the [`bumpalo`](https://docs.rs/bumpalo) allocator:
333    ///
334    /// ```
335    /// # #[cfg(all(feature = "default-hasher", feature = "allocator-api2"))] {
336    /// use iddqd::{BiHashMap, BiHashItem, bi_upcast};
337    /// # use iddqd_test_utils::bumpalo;
338    ///
339    /// #[derive(Debug, PartialEq, Eq)]
340    /// struct Item {
341    ///     id: u32,
342    ///     name: String,
343    ///     value: i32,
344    /// }
345    ///
346    /// impl BiHashItem for Item {
347    ///     type K1<'a> = u32;
348    ///     type K2<'a> = &'a str;
349    ///
350    ///     fn key1(&self) -> Self::K1<'_> {
351    ///         self.id
352    ///     }
353    ///     fn key2(&self) -> Self::K2<'_> {
354    ///         &self.name
355    ///     }
356    ///     bi_upcast!();
357    /// }
358    ///
359    /// // Define a new allocator.
360    /// let bump = bumpalo::Bump::new();
361    /// // Create a new BiHashMap with capacity using the allocator.
362    /// let map: BiHashMap<Item, _, &bumpalo::Bump> = BiHashMap::with_capacity_in(10, &bump);
363    /// assert!(map.capacity() >= 10);
364    /// assert!(map.is_empty());
365    /// # }
366    /// ```
367    pub fn with_capacity_in(capacity: usize, alloc: A) -> Self {
368        Self {
369            items: ItemSet::with_capacity_in(capacity, alloc.clone()),
370            tables: BiHashMapTables::with_capacity_and_hasher_in(
371                capacity,
372                DefaultHashBuilder::default(),
373                alloc,
374            ),
375        }
376    }
377}
378
379impl<T: BiHashItem, S: Clone + BuildHasher, A: Clone + Allocator>
380    BiHashMap<T, S, A>
381{
382    /// Creates a new, empty `BiHashMap` with the given hasher and allocator.
383    ///
384    /// Requires the `allocator-api2` feature to be enabled.
385    ///
386    /// # Examples
387    ///
388    /// Using the [`bumpalo`](https://docs.rs/bumpalo) allocator:
389    ///
390    /// ```
391    /// # #[cfg(feature = "allocator-api2")] {
392    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
393    /// use std::collections::hash_map::RandomState;
394    /// # use iddqd_test_utils::bumpalo;
395    ///
396    /// #[derive(Debug, PartialEq, Eq)]
397    /// struct Item {
398    ///     id: u32,
399    ///     name: String,
400    ///     value: i32,
401    /// }
402    ///
403    /// impl BiHashItem for Item {
404    ///     type K1<'a> = u32;
405    ///     type K2<'a> = &'a str;
406    ///
407    ///     fn key1(&self) -> Self::K1<'_> {
408    ///         self.id
409    ///     }
410    ///     fn key2(&self) -> Self::K2<'_> {
411    ///         &self.name
412    ///     }
413    ///     bi_upcast!();
414    /// }
415    ///
416    /// // Define a new allocator.
417    /// let bump = bumpalo::Bump::new();
418    /// let hasher = RandomState::new();
419    /// // Create a new BiHashMap with hasher using the allocator.
420    /// let map: BiHashMap<Item, _, &bumpalo::Bump> =
421    ///     BiHashMap::with_hasher_in(hasher, &bump);
422    /// assert!(map.is_empty());
423    /// # }
424    /// ```
425    pub fn with_hasher_in(hasher: S, alloc: A) -> Self {
426        Self {
427            items: ItemSet::with_capacity_in(0, alloc.clone()),
428            tables: BiHashMapTables::with_capacity_and_hasher_in(
429                0, hasher, alloc,
430            ),
431        }
432    }
433
434    /// Creates a new, empty `BiHashMap` with the given capacity, hasher, and
435    /// allocator.
436    ///
437    /// Requires the `allocator-api2` feature to be enabled.
438    ///
439    /// # Examples
440    ///
441    /// Using the [`bumpalo`](https://docs.rs/bumpalo) allocator:
442    ///
443    /// ```
444    /// # #[cfg(feature = "allocator-api2")] {
445    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
446    /// use std::collections::hash_map::RandomState;
447    /// # use iddqd_test_utils::bumpalo;
448    ///
449    /// #[derive(Debug, PartialEq, Eq)]
450    /// struct Item {
451    ///     id: u32,
452    ///     name: String,
453    ///     value: i32,
454    /// }
455    ///
456    /// impl BiHashItem for Item {
457    ///     type K1<'a> = u32;
458    ///     type K2<'a> = &'a str;
459    ///
460    ///     fn key1(&self) -> Self::K1<'_> {
461    ///         self.id
462    ///     }
463    ///     fn key2(&self) -> Self::K2<'_> {
464    ///         &self.name
465    ///     }
466    ///     bi_upcast!();
467    /// }
468    ///
469    /// // Define a new allocator.
470    /// let bump = bumpalo::Bump::new();
471    /// let hasher = RandomState::new();
472    /// // Create a new BiHashMap with capacity and hasher using the allocator.
473    /// let map: BiHashMap<Item, _, &bumpalo::Bump> =
474    ///     BiHashMap::with_capacity_and_hasher_in(10, hasher, &bump);
475    /// assert!(map.capacity() >= 10);
476    /// assert!(map.is_empty());
477    /// # }
478    /// ```
479    pub fn with_capacity_and_hasher_in(
480        capacity: usize,
481        hasher: S,
482        alloc: A,
483    ) -> Self {
484        Self {
485            items: ItemSet::with_capacity_in(capacity, alloc.clone()),
486            tables: BiHashMapTables::with_capacity_and_hasher_in(
487                capacity, hasher, alloc,
488            ),
489        }
490    }
491}
492
493impl<T: BiHashItem, S: Clone + BuildHasher, A: Allocator> BiHashMap<T, S, A> {
494    /// Returns the hasher.
495    #[cfg(feature = "daft")]
496    #[inline]
497    pub(crate) fn hasher(&self) -> &S {
498        self.tables.hasher()
499    }
500
501    /// Returns the allocator.
502    ///
503    /// Requires the `allocator-api2` feature to be enabled.
504    ///
505    /// # Examples
506    ///
507    /// Using the [`bumpalo`](https://docs.rs/bumpalo) allocator:
508    ///
509    /// ```
510    /// # #[cfg(all(feature = "default-hasher", feature = "allocator-api2"))] {
511    /// use iddqd::{BiHashMap, BiHashItem, bi_upcast};
512    /// # use iddqd_test_utils::bumpalo;
513    ///
514    /// #[derive(Debug, PartialEq, Eq)]
515    /// struct Item {
516    ///     id: u32,
517    ///     name: String,
518    ///     value: i32,
519    /// }
520    ///
521    /// impl BiHashItem for Item {
522    ///     type K1<'a> = u32;
523    ///     type K2<'a> = &'a str;
524    ///
525    ///     fn key1(&self) -> Self::K1<'_> {
526    ///         self.id
527    ///     }
528    ///     fn key2(&self) -> Self::K2<'_> {
529    ///         &self.name
530    ///     }
531    ///     bi_upcast!();
532    /// }
533    ///
534    /// // Define a new allocator.
535    /// let bump = bumpalo::Bump::new();
536    /// // Create a new BiHashMap using the allocator.
537    /// let map: BiHashMap<Item, _, &bumpalo::Bump> = BiHashMap::new_in(&bump);
538    /// let _allocator = map.allocator();
539    /// # }
540    /// ```
541    #[inline]
542    pub fn allocator(&self) -> &A {
543        self.items.allocator()
544    }
545
546    /// Returns the currently allocated capacity of the map.
547    ///
548    /// # Examples
549    ///
550    /// ```
551    /// # #[cfg(feature = "default-hasher")] {
552    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
553    ///
554    /// #[derive(Debug, PartialEq, Eq)]
555    /// struct Item {
556    ///     id: u32,
557    ///     name: String,
558    ///     value: i32,
559    /// }
560    ///
561    /// impl BiHashItem for Item {
562    ///     type K1<'a> = u32;
563    ///     type K2<'a> = &'a str;
564    ///
565    ///     fn key1(&self) -> Self::K1<'_> {
566    ///         self.id
567    ///     }
568    ///     fn key2(&self) -> Self::K2<'_> {
569    ///         &self.name
570    ///     }
571    ///     bi_upcast!();
572    /// }
573    ///
574    /// let map: BiHashMap<Item> = BiHashMap::with_capacity(10);
575    /// assert!(map.capacity() >= 10);
576    ///
577    /// let empty_map: BiHashMap<Item> = BiHashMap::new();
578    /// assert!(empty_map.capacity() >= 0);
579    /// # }
580    /// ```
581    pub fn capacity(&self) -> usize {
582        // items and tables.capacity might theoretically diverge: use
583        // items.capacity.
584        self.items.capacity()
585    }
586
587    /// Returns true if the map contains no items.
588    ///
589    /// # Examples
590    ///
591    /// ```
592    /// # #[cfg(feature = "default-hasher")] {
593    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
594    ///
595    /// #[derive(Debug, PartialEq, Eq)]
596    /// struct Item {
597    ///     id: u32,
598    ///     name: String,
599    ///     value: i32,
600    /// }
601    ///
602    /// impl BiHashItem for Item {
603    ///     type K1<'a> = u32;
604    ///     type K2<'a> = &'a str;
605    ///
606    ///     fn key1(&self) -> Self::K1<'_> {
607    ///         self.id
608    ///     }
609    ///     fn key2(&self) -> Self::K2<'_> {
610    ///         &self.name
611    ///     }
612    ///     bi_upcast!();
613    /// }
614    ///
615    /// let mut map = BiHashMap::new();
616    /// assert!(map.is_empty());
617    ///
618    /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
619    ///     .unwrap();
620    /// assert!(!map.is_empty());
621    /// # }
622    /// ```
623    #[inline]
624    pub fn is_empty(&self) -> bool {
625        self.items.is_empty()
626    }
627
628    /// Returns the number of items in the map.
629    ///
630    /// # Examples
631    ///
632    /// ```
633    /// # #[cfg(feature = "default-hasher")] {
634    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
635    ///
636    /// #[derive(Debug, PartialEq, Eq)]
637    /// struct Item {
638    ///     id: u32,
639    ///     name: String,
640    ///     value: i32,
641    /// }
642    ///
643    /// impl BiHashItem for Item {
644    ///     type K1<'a> = u32;
645    ///     type K2<'a> = &'a str;
646    ///
647    ///     fn key1(&self) -> Self::K1<'_> {
648    ///         self.id
649    ///     }
650    ///     fn key2(&self) -> Self::K2<'_> {
651    ///         &self.name
652    ///     }
653    ///     bi_upcast!();
654    /// }
655    ///
656    /// let mut map = BiHashMap::new();
657    /// assert_eq!(map.len(), 0);
658    ///
659    /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
660    ///     .unwrap();
661    /// map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
662    ///     .unwrap();
663    /// assert_eq!(map.len(), 2);
664    /// # }
665    /// ```
666    #[inline]
667    pub fn len(&self) -> usize {
668        self.items.len()
669    }
670
671    /// Returns an iterator over all items in the map.
672    ///
673    /// Similar to [`HashMap`], the iteration order is arbitrary and not
674    /// guaranteed to be stable.
675    ///
676    /// [`HashMap`]: std::collections::HashMap
677    /// # Examples
678    ///
679    /// ```
680    /// # #[cfg(feature = "default-hasher")] {
681    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
682    ///
683    /// #[derive(Debug, PartialEq, Eq)]
684    /// struct Item {
685    ///     id: u32,
686    ///     name: String,
687    ///     value: i32,
688    /// }
689    ///
690    /// impl BiHashItem for Item {
691    ///     type K1<'a> = u32;
692    ///     type K2<'a> = &'a str;
693    ///
694    ///     fn key1(&self) -> Self::K1<'_> {
695    ///         self.id
696    ///     }
697    ///     fn key2(&self) -> Self::K2<'_> {
698    ///         &self.name
699    ///     }
700    ///     bi_upcast!();
701    /// }
702    ///
703    /// let mut map = BiHashMap::new();
704    /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
705    ///     .unwrap();
706    /// map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
707    ///     .unwrap();
708    ///
709    /// let mut values: Vec<i32> = map.iter().map(|item| item.value).collect();
710    /// values.sort();
711    /// assert_eq!(values, vec![42, 99]);
712    /// # }
713    /// ```
714    #[inline]
715    pub fn iter(&self) -> Iter<'_, T> {
716        Iter::new(&self.items)
717    }
718
719    /// Iterates over the items in the map, allowing for mutation.
720    ///
721    /// Similar to [`HashMap`], the iteration order is arbitrary and not
722    /// guaranteed to be stable.
723    ///
724    /// # Examples
725    ///
726    /// ```
727    /// # #[cfg(feature = "default-hasher")] {
728    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
729    ///
730    /// #[derive(Debug, PartialEq, Eq)]
731    /// struct Item {
732    ///     id: u32,
733    ///     name: String,
734    ///     value: i32,
735    /// }
736    ///
737    /// impl BiHashItem for Item {
738    ///     type K1<'a> = u32;
739    ///     type K2<'a> = &'a str;
740    ///
741    ///     fn key1(&self) -> Self::K1<'_> {
742    ///         self.id
743    ///     }
744    ///     fn key2(&self) -> Self::K2<'_> {
745    ///         &self.name
746    ///     }
747    ///     bi_upcast!();
748    /// }
749    ///
750    /// let mut map = BiHashMap::new();
751    /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
752    ///     .unwrap();
753    /// map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
754    ///     .unwrap();
755    ///
756    /// for mut item in map.iter_mut() {
757    ///     item.value += 10;
758    /// }
759    ///
760    /// assert_eq!(map.get1(&1).unwrap().value, 52);
761    /// assert_eq!(map.get1(&2).unwrap().value, 109);
762    /// # }
763    /// ```
764    ///
765    /// [`HashMap`]: std::collections::HashMap
766    #[inline]
767    pub fn iter_mut(&mut self) -> IterMut<'_, T, S, A> {
768        IterMut::new(&self.tables, &mut self.items)
769    }
770
771    /// Checks general invariants of the map.
772    ///
773    /// The code below always upholds these invariants, but it's useful to have
774    /// an explicit check for tests.
775    #[doc(hidden)]
776    pub fn validate(
777        &self,
778        compactness: ValidateCompact,
779    ) -> Result<(), ValidationError>
780    where
781        T: fmt::Debug,
782    {
783        self.items.validate(compactness)?;
784        self.tables.validate(self.len(), compactness)?;
785
786        // Check that the indexes are all correct.
787        for (&ix, item) in self.items.iter() {
788            let key1 = item.key1();
789            let key2 = item.key2();
790
791            let Some(ix1) = self.find1_index(&key1) else {
792                return Err(ValidationError::general(format!(
793                    "item at index {ix} has no key1 index"
794                )));
795            };
796            let Some(ix2) = self.find2_index(&key2) else {
797                return Err(ValidationError::general(format!(
798                    "item at index {ix} has no key2 index"
799                )));
800            };
801
802            if ix1 != ix || ix2 != ix {
803                return Err(ValidationError::general(format!(
804                    "item at index {ix} has inconsistent indexes: {ix1}/{ix2}"
805                )));
806            }
807        }
808
809        Ok(())
810    }
811
812    /// Inserts a value into the map, removing any conflicting items and
813    /// returning a list of those items.
814    ///
815    /// # Examples
816    ///
817    /// ```
818    /// # #[cfg(feature = "default-hasher")] {
819    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
820    ///
821    /// #[derive(Debug, PartialEq, Eq)]
822    /// struct Item {
823    ///     id: u32,
824    ///     name: String,
825    ///     value: i32,
826    /// }
827    ///
828    /// impl BiHashItem for Item {
829    ///     type K1<'a> = u32;
830    ///     type K2<'a> = &'a str;
831    ///
832    ///     fn key1(&self) -> Self::K1<'_> {
833    ///         self.id
834    ///     }
835    ///     fn key2(&self) -> Self::K2<'_> {
836    ///         &self.name
837    ///     }
838    ///     bi_upcast!();
839    /// }
840    ///
841    /// let mut map = BiHashMap::new();
842    /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
843    ///     .unwrap();
844    /// map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
845    ///     .unwrap();
846    ///
847    /// // Insert an item with conflicting key1
848    /// let removed = map.insert_overwrite(Item {
849    ///     id: 1,
850    ///     name: "baz".to_string(),
851    ///     value: 100,
852    /// });
853    /// assert_eq!(removed.len(), 1);
854    /// assert_eq!(removed[0].name, "foo");
855    /// assert_eq!(removed[0].value, 42);
856    ///
857    /// assert_eq!(map.len(), 2);
858    /// assert_eq!(map.get1(&1).unwrap().name, "baz");
859    /// # }
860    /// ```
861    #[doc(alias = "insert")]
862    pub fn insert_overwrite(&mut self, value: T) -> Vec<T> {
863        // Trying to write this function for maximal efficiency can get very
864        // tricky, requiring delicate handling of indexes. We follow a very
865        // simple approach instead:
866        //
867        // 1. Remove items corresponding to keys that are already in the map.
868        // 2. Add the item to the map.
869
870        let mut duplicates = Vec::new();
871        duplicates.extend(self.remove1(&value.key1()));
872        duplicates.extend(self.remove2(&value.key2()));
873
874        if self.insert_unique(value).is_err() {
875            // We should never get here, because we just removed all the
876            // duplicates.
877            panic!("insert_unique failed after removing duplicates");
878        }
879
880        duplicates
881    }
882
883    /// Inserts a value into the set, returning an error if any duplicates were
884    /// added.
885    ///
886    /// # Examples
887    ///
888    /// ```
889    /// # #[cfg(feature = "default-hasher")] {
890    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
891    ///
892    /// #[derive(Debug, PartialEq, Eq)]
893    /// struct Item {
894    ///     id: u32,
895    ///     name: String,
896    ///     value: i32,
897    /// }
898    ///
899    /// impl BiHashItem for Item {
900    ///     type K1<'a> = u32;
901    ///     type K2<'a> = &'a str;
902    ///
903    ///     fn key1(&self) -> Self::K1<'_> {
904    ///         self.id
905    ///     }
906    ///     fn key2(&self) -> Self::K2<'_> {
907    ///         &self.name
908    ///     }
909    ///     bi_upcast!();
910    /// }
911    ///
912    /// let mut map = BiHashMap::new();
913    ///
914    /// // Successful insertion
915    /// assert!(
916    ///     map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
917    ///         .is_ok()
918    /// );
919    /// assert!(
920    ///     map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
921    ///         .is_ok()
922    /// );
923    ///
924    /// // Duplicate key1
925    /// assert!(
926    ///     map.insert_unique(Item { id: 1, name: "baz".to_string(), value: 100 })
927    ///         .is_err()
928    /// );
929    ///
930    /// // Duplicate key2
931    /// assert!(
932    ///     map.insert_unique(Item { id: 3, name: "foo".to_string(), value: 200 })
933    ///         .is_err()
934    /// );
935    /// # }
936    /// ```
937    pub fn insert_unique(
938        &mut self,
939        value: T,
940    ) -> Result<(), DuplicateItem<T, &T>> {
941        let _ = self.insert_unique_impl(value)?;
942        Ok(())
943    }
944
945    /// Returns true if the map contains a single item that matches both `key1` and `key2`.
946    ///
947    /// # Examples
948    ///
949    /// ```
950    /// # #[cfg(feature = "default-hasher")] {
951    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
952    ///
953    /// #[derive(Debug, PartialEq, Eq)]
954    /// struct Item {
955    ///     id: u32,
956    ///     name: String,
957    ///     value: i32,
958    /// }
959    ///
960    /// impl BiHashItem for Item {
961    ///     type K1<'a> = u32;
962    ///     type K2<'a> = &'a str;
963    ///
964    ///     fn key1(&self) -> Self::K1<'_> {
965    ///         self.id
966    ///     }
967    ///     fn key2(&self) -> Self::K2<'_> {
968    ///         &self.name
969    ///     }
970    ///     bi_upcast!();
971    /// }
972    ///
973    /// let mut map = BiHashMap::new();
974    /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 }).unwrap();
975    /// map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 }).unwrap();
976    ///
977    /// assert!(map.contains_key_unique(&1, &"foo"));
978    /// assert!(map.contains_key_unique(&2, &"bar"));
979    /// assert!(!map.contains_key_unique(&1, &"bar")); // key1 exists but key2 doesn't match
980    /// assert!(!map.contains_key_unique(&3, &"baz")); // neither key exists
981    /// # }
982    /// ```
983    pub fn contains_key_unique<'a, Q1, Q2>(
984        &'a self,
985        key1: &Q1,
986        key2: &Q2,
987    ) -> bool
988    where
989        Q1: Hash + Equivalent<T::K1<'a>> + ?Sized,
990        Q2: Hash + Equivalent<T::K2<'a>> + ?Sized,
991    {
992        self.get_unique(key1, key2).is_some()
993    }
994
995    /// Gets a reference to the unique item associated with the given `key1` and
996    /// `key2`, if it exists.
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 }).unwrap();
1026    /// map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 }).unwrap();
1027    ///
1028    /// assert_eq!(map.get_unique(&1, &"foo").unwrap().value, 42);
1029    /// assert_eq!(map.get_unique(&2, &"bar").unwrap().value, 99);
1030    /// assert!(map.get_unique(&1, &"bar").is_none()); // key1 exists but key2 doesn't match
1031    /// assert!(map.get_unique(&3, &"baz").is_none()); // neither key exists
1032    /// # }
1033    /// ```
1034    pub fn get_unique<'a, Q1, Q2>(
1035        &'a self,
1036        key1: &Q1,
1037        key2: &Q2,
1038    ) -> Option<&'a T>
1039    where
1040        Q1: Hash + Equivalent<T::K1<'a>> + ?Sized,
1041        Q2: Hash + Equivalent<T::K2<'a>> + ?Sized,
1042    {
1043        let index = self.find1_index(key1)?;
1044        let item = &self.items[index];
1045        if key2.equivalent(&item.key2()) { Some(item) } else { None }
1046    }
1047
1048    /// Gets a mutable reference to the unique item associated with the given
1049    /// `key1` and `key2`, if it exists.
1050    pub fn get_mut_unique<'a, Q1, Q2>(
1051        &'a mut self,
1052        key1: &Q1,
1053        key2: &Q2,
1054    ) -> Option<RefMut<'a, T, S>>
1055    where
1056        Q1: Hash + Equivalent<T::K1<'a>> + ?Sized,
1057        Q2: Hash + Equivalent<T::K2<'a>> + ?Sized,
1058    {
1059        let (dormant_map, index) = {
1060            let (map, dormant_map) = DormantMutRef::new(self);
1061            let index = map.find1_index(key1)?;
1062            // Check key2 match before proceeding
1063            if !key2.equivalent(&map.items[index].key2()) {
1064                return None;
1065            }
1066            (dormant_map, index)
1067        };
1068
1069        // SAFETY: `map` is not used after this point.
1070        let awakened_map = unsafe { dormant_map.awaken() };
1071        let item = &mut awakened_map.items[index];
1072        let hashes =
1073            awakened_map.tables.make_hashes::<T>(&item.key1(), &item.key2());
1074        Some(RefMut::new(hashes, item))
1075    }
1076
1077    /// Removes the item uniquely identified by `key1` and `key2`, if it exists.
1078    pub fn remove_unique<'a, Q1, Q2>(
1079        &'a mut self,
1080        key1: &Q1,
1081        key2: &Q2,
1082    ) -> Option<T>
1083    where
1084        Q1: Hash + Equivalent<T::K1<'a>> + ?Sized,
1085        Q2: Hash + Equivalent<T::K2<'a>> + ?Sized,
1086    {
1087        let (dormant_map, remove_index) = {
1088            let (map, dormant_map) = DormantMutRef::new(self);
1089            let remove_index = map.find1_index(key1)?;
1090            if !key2.equivalent(&map.items[remove_index].key2()) {
1091                return None;
1092            }
1093            (dormant_map, remove_index)
1094        };
1095
1096        // SAFETY: `map` is not used after this point.
1097        let awakened_map = unsafe { dormant_map.awaken() };
1098
1099        awakened_map.remove_by_index(remove_index)
1100    }
1101
1102    /// Returns true if the map contains the given `key1`.
1103    ///
1104    /// # Examples
1105    ///
1106    /// ```
1107    /// # #[cfg(feature = "default-hasher")] {
1108    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
1109    ///
1110    /// #[derive(Debug, PartialEq, Eq)]
1111    /// struct Item {
1112    ///     id: u32,
1113    ///     name: String,
1114    ///     value: i32,
1115    /// }
1116    ///
1117    /// impl BiHashItem for Item {
1118    ///     type K1<'a> = u32;
1119    ///     type K2<'a> = &'a str;
1120    ///
1121    ///     fn key1(&self) -> Self::K1<'_> {
1122    ///         self.id
1123    ///     }
1124    ///     fn key2(&self) -> Self::K2<'_> {
1125    ///         &self.name
1126    ///     }
1127    ///     bi_upcast!();
1128    /// }
1129    ///
1130    /// let mut map = BiHashMap::new();
1131    /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
1132    ///     .unwrap();
1133    /// map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
1134    ///     .unwrap();
1135    ///
1136    /// assert!(map.contains_key1(&1));
1137    /// assert!(map.contains_key1(&2));
1138    /// assert!(!map.contains_key1(&3));
1139    /// # }
1140    /// ```
1141    pub fn contains_key1<'a, Q>(&'a self, key1: &Q) -> bool
1142    where
1143        Q: Hash + Equivalent<T::K1<'a>> + ?Sized,
1144    {
1145        self.find1_index(key1).is_some()
1146    }
1147
1148    /// Gets a reference to the value associated with the given `key1`.
1149    ///
1150    /// # Examples
1151    ///
1152    /// ```
1153    /// # #[cfg(feature = "default-hasher")] {
1154    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
1155    ///
1156    /// #[derive(Debug, PartialEq, Eq)]
1157    /// struct Item {
1158    ///     id: u32,
1159    ///     name: String,
1160    ///     value: i32,
1161    /// }
1162    ///
1163    /// impl BiHashItem for Item {
1164    ///     type K1<'a> = u32;
1165    ///     type K2<'a> = &'a str;
1166    ///
1167    ///     fn key1(&self) -> Self::K1<'_> {
1168    ///         self.id
1169    ///     }
1170    ///     fn key2(&self) -> Self::K2<'_> {
1171    ///         &self.name
1172    ///     }
1173    ///     bi_upcast!();
1174    /// }
1175    ///
1176    /// let mut map = BiHashMap::new();
1177    /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
1178    ///     .unwrap();
1179    /// map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
1180    ///     .unwrap();
1181    ///
1182    /// assert_eq!(map.get1(&1).unwrap().value, 42);
1183    /// assert_eq!(map.get1(&2).unwrap().value, 99);
1184    /// assert!(map.get1(&3).is_none());
1185    /// # }
1186    /// ```
1187    pub fn get1<'a, Q>(&'a self, key1: &Q) -> Option<&'a T>
1188    where
1189        Q: Hash + Equivalent<T::K1<'a>> + ?Sized,
1190    {
1191        self.find1(key1)
1192    }
1193
1194    /// Gets a mutable reference to the value associated with the given `key1`.
1195    pub fn get1_mut<'a, Q>(&'a mut self, key1: &Q) -> Option<RefMut<'a, T, S>>
1196    where
1197        Q: Hash + Equivalent<T::K1<'a>> + ?Sized,
1198    {
1199        let (dormant_map, index) = {
1200            let (map, dormant_map) = DormantMutRef::new(self);
1201            let index = map.find1_index(key1)?;
1202            (dormant_map, index)
1203        };
1204
1205        // SAFETY: `map` is not used after this point.
1206        let awakened_map = unsafe { dormant_map.awaken() };
1207        let item = &mut awakened_map.items[index];
1208        let hashes =
1209            awakened_map.tables.make_hashes::<T>(&item.key1(), &item.key2());
1210        Some(RefMut::new(hashes, item))
1211    }
1212
1213    /// Removes an item from the map by its `key1`.
1214    ///
1215    /// # Examples
1216    ///
1217    /// ```
1218    /// # #[cfg(feature = "default-hasher")] {
1219    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
1220    ///
1221    /// #[derive(Debug, PartialEq, Eq)]
1222    /// struct Item {
1223    ///     id: u32,
1224    ///     name: String,
1225    ///     value: i32,
1226    /// }
1227    ///
1228    /// impl BiHashItem for Item {
1229    ///     type K1<'a> = u32;
1230    ///     type K2<'a> = &'a str;
1231    ///
1232    ///     fn key1(&self) -> Self::K1<'_> {
1233    ///         self.id
1234    ///     }
1235    ///     fn key2(&self) -> Self::K2<'_> {
1236    ///         &self.name
1237    ///     }
1238    ///     bi_upcast!();
1239    /// }
1240    ///
1241    /// let mut map = BiHashMap::new();
1242    /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
1243    ///     .unwrap();
1244    /// map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
1245    ///     .unwrap();
1246    ///
1247    /// let removed = map.remove1(&1);
1248    /// assert_eq!(removed.unwrap().value, 42);
1249    /// assert_eq!(map.len(), 1);
1250    /// assert!(map.get1(&1).is_none());
1251    /// assert!(map.remove1(&3).is_none());
1252    /// # }
1253    /// ```
1254    pub fn remove1<'a, Q>(&'a mut self, key1: &Q) -> Option<T>
1255    where
1256        Q: Hash + Equivalent<T::K1<'a>> + ?Sized,
1257    {
1258        let (dormant_map, remove_index) = {
1259            let (map, dormant_map) = DormantMutRef::new(self);
1260            let remove_index = map.find1_index(key1)?;
1261            (dormant_map, remove_index)
1262        };
1263
1264        // SAFETY: `map` is not used after this point.
1265        let awakened_map = unsafe { dormant_map.awaken() };
1266
1267        awakened_map.remove_by_index(remove_index)
1268    }
1269
1270    /// Returns true if the map contains the given `key2`.
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 })
1300    ///     .unwrap();
1301    /// map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
1302    ///     .unwrap();
1303    ///
1304    /// assert!(map.contains_key2(&"foo"));
1305    /// assert!(map.contains_key2(&"bar"));
1306    /// assert!(!map.contains_key2(&"baz"));
1307    /// # }
1308    /// ```
1309    pub fn contains_key2<'a, Q>(&'a self, key2: &Q) -> bool
1310    where
1311        Q: Hash + Equivalent<T::K2<'a>> + ?Sized,
1312    {
1313        self.find2_index(key2).is_some()
1314    }
1315
1316    /// Gets a reference to the value associated with the given `key2`.
1317    ///
1318    /// # Examples
1319    ///
1320    /// ```
1321    /// # #[cfg(feature = "default-hasher")] {
1322    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
1323    ///
1324    /// #[derive(Debug, PartialEq, Eq)]
1325    /// struct Item {
1326    ///     id: u32,
1327    ///     name: String,
1328    ///     value: i32,
1329    /// }
1330    ///
1331    /// impl BiHashItem for Item {
1332    ///     type K1<'a> = u32;
1333    ///     type K2<'a> = &'a str;
1334    ///
1335    ///     fn key1(&self) -> Self::K1<'_> {
1336    ///         self.id
1337    ///     }
1338    ///     fn key2(&self) -> Self::K2<'_> {
1339    ///         &self.name
1340    ///     }
1341    ///     bi_upcast!();
1342    /// }
1343    ///
1344    /// let mut map = BiHashMap::new();
1345    /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
1346    ///     .unwrap();
1347    /// map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
1348    ///     .unwrap();
1349    ///
1350    /// assert_eq!(map.get2(&"foo").unwrap().value, 42);
1351    /// assert_eq!(map.get2(&"bar").unwrap().value, 99);
1352    /// assert!(map.get2(&"baz").is_none());
1353    /// # }
1354    /// ```
1355    pub fn get2<'a, Q>(&'a self, key2: &Q) -> Option<&'a T>
1356    where
1357        Q: Hash + Equivalent<T::K2<'a>> + ?Sized,
1358    {
1359        self.find2(key2)
1360    }
1361
1362    /// Gets a mutable reference to the value associated with the given `key2`.
1363    ///
1364    /// # Examples
1365    ///
1366    /// ```
1367    /// # #[cfg(feature = "default-hasher")] {
1368    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
1369    ///
1370    /// #[derive(Debug, PartialEq, Eq)]
1371    /// struct Item {
1372    ///     id: u32,
1373    ///     name: String,
1374    ///     value: i32,
1375    /// }
1376    ///
1377    /// impl BiHashItem for Item {
1378    ///     type K1<'a> = u32;
1379    ///     type K2<'a> = &'a str;
1380    ///
1381    ///     fn key1(&self) -> Self::K1<'_> {
1382    ///         self.id
1383    ///     }
1384    ///     fn key2(&self) -> Self::K2<'_> {
1385    ///         &self.name
1386    ///     }
1387    ///     bi_upcast!();
1388    /// }
1389    ///
1390    /// let mut map = BiHashMap::new();
1391    /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
1392    ///     .unwrap();
1393    ///
1394    /// if let Some(mut item_ref) = map.get2_mut(&"foo") {
1395    ///     item_ref.value = 100;
1396    /// }
1397    ///
1398    /// assert_eq!(map.get2(&"foo").unwrap().value, 100);
1399    /// # }
1400    /// ```
1401    pub fn get2_mut<'a, Q>(&'a mut self, key2: &Q) -> Option<RefMut<'a, T, S>>
1402    where
1403        Q: Hash + Equivalent<T::K2<'a>> + ?Sized,
1404    {
1405        let (dormant_map, index) = {
1406            let (map, dormant_map) = DormantMutRef::new(self);
1407            let index = map.find2_index(key2)?;
1408            (dormant_map, index)
1409        };
1410
1411        // SAFETY: `map` is not used after this point.
1412        let awakened_map = unsafe { dormant_map.awaken() };
1413        let item = &mut awakened_map.items[index];
1414        let hashes =
1415            awakened_map.tables.make_hashes::<T>(&item.key1(), &item.key2());
1416        Some(RefMut::new(hashes, item))
1417    }
1418
1419    /// Removes an item from the map by its `key2`.
1420    ///
1421    /// # Examples
1422    ///
1423    /// ```
1424    /// # #[cfg(feature = "default-hasher")] {
1425    /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
1426    ///
1427    /// #[derive(Debug, PartialEq, Eq)]
1428    /// struct Item {
1429    ///     id: u32,
1430    ///     name: String,
1431    ///     value: i32,
1432    /// }
1433    ///
1434    /// impl BiHashItem for Item {
1435    ///     type K1<'a> = u32;
1436    ///     type K2<'a> = &'a str;
1437    ///
1438    ///     fn key1(&self) -> Self::K1<'_> {
1439    ///         self.id
1440    ///     }
1441    ///     fn key2(&self) -> Self::K2<'_> {
1442    ///         &self.name
1443    ///     }
1444    ///     bi_upcast!();
1445    /// }
1446    ///
1447    /// let mut map = BiHashMap::new();
1448    /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
1449    ///     .unwrap();
1450    /// map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
1451    ///     .unwrap();
1452    ///
1453    /// let removed = map.remove2(&"foo");
1454    /// assert_eq!(removed.unwrap().value, 42);
1455    /// assert_eq!(map.len(), 1);
1456    /// assert!(map.get2(&"foo").is_none());
1457    /// assert!(map.remove2(&"baz").is_none());
1458    /// # }
1459    /// ```
1460    pub fn remove2<'a, Q>(&'a mut self, key2: &Q) -> Option<T>
1461    where
1462        Q: Hash + Equivalent<T::K2<'a>> + ?Sized,
1463    {
1464        let (dormant_map, remove_index) = {
1465            let (map, dormant_map) = DormantMutRef::new(self);
1466            let remove_index = map.find2_index(key2)?;
1467            (dormant_map, remove_index)
1468        };
1469
1470        // SAFETY: `map` is not used after this point.
1471        let awakened_map = unsafe { dormant_map.awaken() };
1472
1473        awakened_map.remove_by_index(remove_index)
1474    }
1475
1476    /// Retrieves an entry by its keys.
1477    ///
1478    /// Due to borrow checker limitations, this always accepts owned keys rather
1479    /// than a borrowed form of them.
1480    ///
1481    /// # Examples
1482    ///
1483    /// ```
1484    /// # #[cfg(feature = "default-hasher")] {
1485    /// use iddqd::{BiHashItem, BiHashMap, bi_hash_map, bi_upcast};
1486    ///
1487    /// #[derive(Debug, PartialEq, Eq)]
1488    /// struct Item {
1489    ///     id: u32,
1490    ///     name: String,
1491    ///     value: i32,
1492    /// }
1493    ///
1494    /// impl BiHashItem for Item {
1495    ///     type K1<'a> = u32;
1496    ///     type K2<'a> = &'a str;
1497    ///
1498    ///     fn key1(&self) -> Self::K1<'_> {
1499    ///         self.id
1500    ///     }
1501    ///     fn key2(&self) -> Self::K2<'_> {
1502    ///         &self.name
1503    ///     }
1504    ///     bi_upcast!();
1505    /// }
1506    ///
1507    /// let mut map = BiHashMap::new();
1508    /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
1509    ///     .unwrap();
1510    ///
1511    /// // Get existing entry
1512    /// match map.entry(1, "foo") {
1513    ///     bi_hash_map::Entry::Occupied(entry) => {
1514    ///         assert_eq!(entry.get().as_unique().unwrap().value, 42);
1515    ///     }
1516    ///     bi_hash_map::Entry::Vacant(_) => panic!("Should be occupied"),
1517    /// }
1518    ///
1519    /// // Try to get a non-existing entry
1520    /// match map.entry(2, "bar") {
1521    ///     bi_hash_map::Entry::Occupied(_) => panic!("Should be vacant"),
1522    ///     bi_hash_map::Entry::Vacant(entry) => {
1523    ///         entry.insert(Item { id: 2, name: "bar".to_string(), value: 99 });
1524    ///     }
1525    /// }
1526    ///
1527    /// assert_eq!(map.len(), 2);
1528    /// # }
1529    /// ```
1530    pub fn entry<'a>(
1531        &'a mut self,
1532        key1: T::K1<'_>,
1533        key2: T::K2<'_>,
1534    ) -> Entry<'a, T, S, A> {
1535        // Why does this always take owned keys? Well, it would seem like we
1536        // should be able to pass in any Q1 and Q2 that are equivalent. That
1537        // results in *this* code compiling fine, but callers have trouble using
1538        // it because the borrow checker believes the keys are borrowed for the
1539        // full 'a rather than a shorter lifetime.
1540        //
1541        // By accepting owned keys, we can use the upcast functions to convert
1542        // them to a shorter lifetime (so this function accepts T::K1<'_> rather
1543        // than T::K1<'a>).
1544        //
1545        // Really, the solution here is to allow GATs to require covariant
1546        // parameters. If that were allowed, the borrow checker should be able
1547        // to figure out that keys don't need to be borrowed for the full 'a,
1548        // just for some shorter lifetime.
1549        let (map, dormant_map) = DormantMutRef::new(self);
1550        let key1 = T::upcast_key1(key1);
1551        let key2 = T::upcast_key2(key2);
1552        let (index1, index2) = {
1553            // index1 and index2 are explicitly typed to show that it has a
1554            // trivial Drop impl that doesn't capture anything from map.
1555            let index1: Option<usize> = map
1556                .tables
1557                .k1_to_item
1558                .find_index(&key1, |index| map.items[index].key1());
1559            let index2: Option<usize> = map
1560                .tables
1561                .k2_to_item
1562                .find_index(&key2, |index| map.items[index].key2());
1563            (index1, index2)
1564        };
1565
1566        match (index1, index2) {
1567            (Some(index1), Some(index2)) if index1 == index2 => {
1568                // The item is already in the map.
1569                drop(key1);
1570                Entry::Occupied(
1571                    // SAFETY: `map` is not used after this point.
1572                    unsafe {
1573                        OccupiedEntry::new(
1574                            dormant_map,
1575                            EntryIndexes::Unique(index1),
1576                        )
1577                    },
1578                )
1579            }
1580            (None, None) => {
1581                let hashes = map.tables.make_hashes::<T>(&key1, &key2);
1582                Entry::Vacant(
1583                    // SAFETY: `map` is not used after this point.
1584                    unsafe { VacantEntry::new(dormant_map, hashes) },
1585                )
1586            }
1587            (index1, index2) => Entry::Occupied(
1588                // SAFETY: `map` is not used after this point.
1589                unsafe {
1590                    OccupiedEntry::new(
1591                        dormant_map,
1592                        EntryIndexes::NonUnique { index1, index2 },
1593                    )
1594                },
1595            ),
1596        }
1597    }
1598
1599    fn find1<'a, Q>(&'a self, k: &Q) -> Option<&'a T>
1600    where
1601        Q: Hash + Equivalent<T::K1<'a>> + ?Sized,
1602    {
1603        self.find1_index(k).map(|ix| &self.items[ix])
1604    }
1605
1606    fn find1_index<'a, Q>(&'a self, k: &Q) -> Option<usize>
1607    where
1608        Q: Hash + Equivalent<T::K1<'a>> + ?Sized,
1609    {
1610        self.tables.k1_to_item.find_index(k, |index| self.items[index].key1())
1611    }
1612
1613    fn find2<'a, Q>(&'a self, k: &Q) -> Option<&'a T>
1614    where
1615        Q: Hash + Equivalent<T::K2<'a>> + ?Sized,
1616    {
1617        self.find2_index(k).map(|ix| &self.items[ix])
1618    }
1619
1620    fn find2_index<'a, Q>(&'a self, k: &Q) -> Option<usize>
1621    where
1622        Q: Hash + Equivalent<T::K2<'a>> + ?Sized,
1623    {
1624        self.tables.k2_to_item.find_index(k, |index| self.items[index].key2())
1625    }
1626
1627    pub(super) fn get_by_entry_index(
1628        &self,
1629        indexes: EntryIndexes,
1630    ) -> OccupiedEntryRef<'_, T> {
1631        match indexes {
1632            EntryIndexes::Unique(index) => OccupiedEntryRef::Unique(
1633                self.items.get(index).expect("index is valid"),
1634            ),
1635            EntryIndexes::NonUnique { index1, index2 } => {
1636                let by_key1 = index1
1637                    .map(|k| self.items.get(k).expect("key1 index is valid"));
1638                let by_key2 = index2
1639                    .map(|k| self.items.get(k).expect("key2 index is valid"));
1640                OccupiedEntryRef::NonUnique { by_key1, by_key2 }
1641            }
1642        }
1643    }
1644
1645    pub(super) fn get_by_entry_index_mut(
1646        &mut self,
1647        indexes: EntryIndexes,
1648    ) -> OccupiedEntryMut<'_, T, S> {
1649        match indexes.disjoint_keys() {
1650            DisjointKeys::Unique(index) => {
1651                let item = self.items.get_mut(index).expect("index is valid");
1652                let hashes =
1653                    self.tables.make_hashes::<T>(&item.key1(), &item.key2());
1654                OccupiedEntryMut::Unique(RefMut::new(hashes, item))
1655            }
1656            DisjointKeys::Key1(index1) => {
1657                let item =
1658                    self.items.get_mut(index1).expect("key1 index is valid");
1659                let hashes =
1660                    self.tables.make_hashes::<T>(&item.key1(), &item.key2());
1661                OccupiedEntryMut::NonUnique {
1662                    by_key1: Some(RefMut::new(hashes, item)),
1663                    by_key2: None,
1664                }
1665            }
1666            DisjointKeys::Key2(index2) => {
1667                let item =
1668                    self.items.get_mut(index2).expect("key2 index is valid");
1669                let hashes =
1670                    self.tables.make_hashes::<T>(&item.key1(), &item.key2());
1671                OccupiedEntryMut::NonUnique {
1672                    by_key1: None,
1673                    by_key2: Some(RefMut::new(hashes, item)),
1674                }
1675            }
1676            DisjointKeys::Key12(indexes) => {
1677                let mut items = self.items.get_disjoint_mut(indexes);
1678                let item1 = items[0].take().expect("key1 index is valid");
1679                let item2 = items[1].take().expect("key2 index is valid");
1680                let hashes1 =
1681                    self.tables.make_hashes::<T>(&item1.key1(), &item1.key2());
1682                let hashes2 =
1683                    self.tables.make_hashes::<T>(&item2.key1(), &item2.key2());
1684
1685                OccupiedEntryMut::NonUnique {
1686                    by_key1: Some(RefMut::new(hashes1, item1)),
1687                    by_key2: Some(RefMut::new(hashes2, item2)),
1688                }
1689            }
1690        }
1691    }
1692
1693    pub(super) fn get_by_index_mut(
1694        &mut self,
1695        index: usize,
1696    ) -> Option<RefMut<'_, T, S>> {
1697        let borrowed = self.items.get_mut(index)?;
1698        let hashes =
1699            self.tables.make_hashes::<T>(&borrowed.key1(), &borrowed.key2());
1700        let item = &mut self.items[index];
1701        Some(RefMut::new(hashes, item))
1702    }
1703
1704    pub(super) fn insert_unique_impl(
1705        &mut self,
1706        value: T,
1707    ) -> Result<usize, DuplicateItem<T, &T>> {
1708        let mut duplicates = BTreeSet::new();
1709
1710        // Check for duplicates *before* inserting the new item, because we
1711        // don't want to partially insert the new item and then have to roll
1712        // back.
1713        let (e1, e2) = {
1714            let k1 = value.key1();
1715            let k2 = value.key2();
1716
1717            let e1 = detect_dup_or_insert(
1718                self.tables
1719                    .k1_to_item
1720                    .entry(k1, |index| self.items[index].key1()),
1721                &mut duplicates,
1722            );
1723            let e2 = detect_dup_or_insert(
1724                self.tables
1725                    .k2_to_item
1726                    .entry(k2, |index| self.items[index].key2()),
1727                &mut duplicates,
1728            );
1729            (e1, e2)
1730        };
1731
1732        if !duplicates.is_empty() {
1733            return Err(DuplicateItem::__internal_new(
1734                value,
1735                duplicates.iter().map(|ix| &self.items[*ix]).collect(),
1736            ));
1737        }
1738
1739        let next_index = self.items.insert_at_next_index(value);
1740        // e1 and e2 are all Some because if they were None, duplicates
1741        // would be non-empty, and we'd have bailed out earlier.
1742        e1.unwrap().insert(next_index);
1743        e2.unwrap().insert(next_index);
1744
1745        Ok(next_index)
1746    }
1747
1748    pub(super) fn remove_by_entry_index(
1749        &mut self,
1750        indexes: EntryIndexes,
1751    ) -> Vec<T> {
1752        match indexes {
1753            EntryIndexes::Unique(index) => {
1754                // Since all keys match, we can simply replace the item.
1755                let old_item =
1756                    self.remove_by_index(index).expect("index is valid");
1757                vec![old_item]
1758            }
1759            EntryIndexes::NonUnique { index1, index2 } => {
1760                let mut old_items = Vec::new();
1761                if let Some(index1) = index1 {
1762                    old_items.push(
1763                        self.remove_by_index(index1).expect("index1 is valid"),
1764                    );
1765                }
1766                if let Some(index2) = index2 {
1767                    old_items.push(
1768                        self.remove_by_index(index2).expect("index2 is valid"),
1769                    );
1770                }
1771
1772                old_items
1773            }
1774        }
1775    }
1776
1777    pub(super) fn remove_by_index(&mut self, remove_index: usize) -> Option<T> {
1778        let value = self.items.remove(remove_index)?;
1779
1780        // Remove the value from the tables.
1781        let Ok(item1) =
1782            self.tables.k1_to_item.find_entry(&value.key1(), |index| {
1783                if index == remove_index {
1784                    value.key1()
1785                } else {
1786                    self.items[index].key1()
1787                }
1788            })
1789        else {
1790            // The item was not found.
1791            panic!("remove_index {remove_index} not found in k1_to_item");
1792        };
1793        let Ok(item2) =
1794            self.tables.k2_to_item.find_entry(&value.key2(), |index| {
1795                if index == remove_index {
1796                    value.key2()
1797                } else {
1798                    self.items[index].key2()
1799                }
1800            })
1801        else {
1802            // The item was not found.
1803            panic!("remove_index {remove_index} not found in k2_to_item")
1804        };
1805
1806        item1.remove();
1807        item2.remove();
1808
1809        Some(value)
1810    }
1811
1812    pub(super) fn replace_at_indexes(
1813        &mut self,
1814        indexes: EntryIndexes,
1815        value: T,
1816    ) -> (usize, Vec<T>) {
1817        match indexes {
1818            EntryIndexes::Unique(index) => {
1819                let old_item = &self.items[index];
1820                if old_item.key1() != value.key1() {
1821                    panic!("key1 mismatch");
1822                }
1823                if old_item.key2() != value.key2() {
1824                    panic!("key2 mismatch");
1825                }
1826
1827                // Since all keys match, we can simply replace the item.
1828                let old_item = self.items.replace(index, value);
1829                (index, vec![old_item])
1830            }
1831            EntryIndexes::NonUnique { index1, index2 } => {
1832                let mut old_items = Vec::new();
1833                if let Some(index1) = index1 {
1834                    let old_item = &self.items[index1];
1835                    if old_item.key1() != value.key1() {
1836                        panic!("key1 mismatch");
1837                    }
1838                    old_items.push(self.remove_by_index(index1).unwrap());
1839                }
1840                if let Some(index2) = index2 {
1841                    let old_item = &self.items[index2];
1842                    if old_item.key2() != value.key2() {
1843                        panic!("key2 mismatch");
1844                    }
1845                    old_items.push(self.remove_by_index(index2).unwrap());
1846                }
1847
1848                // Insert the new item.
1849                let Ok(next_index) = self.insert_unique_impl(value) else {
1850                    unreachable!(
1851                        "insert_unique cannot fail after removing duplicates"
1852                    );
1853                };
1854                (next_index, old_items)
1855            }
1856        }
1857    }
1858}
1859
1860impl<'a, T, S, A> fmt::Debug for BiHashMap<T, S, A>
1861where
1862    T: BiHashItem + fmt::Debug,
1863    T::K1<'a>: fmt::Debug,
1864    T::K2<'a>: fmt::Debug,
1865    T: 'a,
1866    A: Allocator,
1867{
1868    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1869        let mut map = f.debug_map();
1870        for item in self.items.values() {
1871            let key: KeyMap<'_, T> =
1872                KeyMap { key1: item.key1(), key2: item.key2() };
1873
1874            // SAFETY:
1875            //
1876            // * Lifetime extension: for a type T and two lifetime params 'a and
1877            //   'b, T<'a> and T<'b> aren't guaranteed to have the same layout,
1878            //   but (a) that is true today and (b) it would be shocking and
1879            //   break half the Rust ecosystem if that were to change in the
1880            //   future.
1881            // * We only use key within the scope of this block before immediately
1882            //   dropping it. In particular, map.entry calls key.fmt() without
1883            //   holding a reference to it.
1884            let key: KeyMap<'a, T> = unsafe {
1885                core::mem::transmute::<KeyMap<'_, T>, KeyMap<'a, T>>(key)
1886            };
1887
1888            map.entry(&key as &dyn fmt::Debug, item);
1889        }
1890        map.finish()
1891    }
1892}
1893
1894struct KeyMap<'a, T: BiHashItem + 'a> {
1895    key1: T::K1<'a>,
1896    key2: T::K2<'a>,
1897}
1898
1899impl<'a, T: BiHashItem + 'a> fmt::Debug for KeyMap<'a, T>
1900where
1901    T::K1<'a>: fmt::Debug,
1902    T::K2<'a>: fmt::Debug,
1903{
1904    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1905        // We don't want to show key1 and key2 as a tuple since it's
1906        // misleading (suggests maps of tuples). The best we can do
1907        // instead is to show "{k1: "abc", k2: "xyz"}"
1908        f.debug_map()
1909            .entry(&StrDisplayAsDebug("k1"), &self.key1)
1910            .entry(&StrDisplayAsDebug("k2"), &self.key2)
1911            .finish()
1912    }
1913}
1914
1915/// The `PartialEq` implementation for `BiHashMap` checks that both maps have
1916/// the same items, regardless of insertion order.
1917///
1918/// # Examples
1919///
1920/// ```
1921/// # #[cfg(feature = "default-hasher")] {
1922/// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
1923///
1924/// #[derive(Debug, PartialEq, Eq)]
1925/// struct Item {
1926///     id: u32,
1927///     name: String,
1928///     value: i32,
1929/// }
1930///
1931/// impl BiHashItem for Item {
1932///     type K1<'a> = u32;
1933///     type K2<'a> = &'a str;
1934///
1935///     fn key1(&self) -> Self::K1<'_> {
1936///         self.id
1937///     }
1938///     fn key2(&self) -> Self::K2<'_> {
1939///         &self.name
1940///     }
1941///     bi_upcast!();
1942/// }
1943///
1944/// let mut map1 = BiHashMap::new();
1945/// map1.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
1946///     .unwrap();
1947/// map1.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
1948///     .unwrap();
1949///
1950/// let mut map2 = BiHashMap::new();
1951/// map2.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
1952///     .unwrap();
1953/// map2.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
1954///     .unwrap();
1955///
1956/// // Maps are equal even if items were inserted in different order
1957/// assert_eq!(map1, map2);
1958///
1959/// map2.insert_unique(Item { id: 3, name: "baz".to_string(), value: 200 })
1960///     .unwrap();
1961/// assert_ne!(map1, map2);
1962/// # }
1963/// ```
1964impl<T: BiHashItem + PartialEq, S: Clone + BuildHasher, A: Allocator> PartialEq
1965    for BiHashMap<T, S, A>
1966{
1967    fn eq(&self, other: &Self) -> bool {
1968        // Implementing PartialEq for BiHashMap is tricky because BiHashMap is
1969        // not semantically like an IndexMap: two maps are equivalent even if
1970        // their items are in a different order. In other words, any permutation
1971        // of items is equivalent.
1972        //
1973        // We also can't sort the items because they're not necessarily Ord.
1974        //
1975        // So we write a custom equality check that checks that each key in one
1976        // map points to the same item as in the other map.
1977
1978        if self.items.len() != other.items.len() {
1979            return false;
1980        }
1981
1982        // Walk over all the items in the first map and check that they point to
1983        // the same item in the second map.
1984        for item in self.items.values() {
1985            let k1 = item.key1();
1986            let k2 = item.key2();
1987
1988            // Check that the indexes are the same in the other map.
1989            let Some(other_ix1) = other.find1_index(&k1) else {
1990                return false;
1991            };
1992            let Some(other_ix2) = other.find2_index(&k2) else {
1993                return false;
1994            };
1995
1996            if other_ix1 != other_ix2 {
1997                // All the keys were present but they didn't point to the same
1998                // item.
1999                return false;
2000            }
2001
2002            // Check that the other map's item is the same as this map's
2003            // item. (This is what we use the `PartialEq` bound on T for.)
2004            //
2005            // Because we've checked that other_ix1 and other_ix2 are
2006            // Some, we know that it is valid and points to the expected item.
2007            let other_item = &other.items[other_ix1];
2008            if item != other_item {
2009                return false;
2010            }
2011        }
2012
2013        true
2014    }
2015}
2016
2017// The Eq bound on T ensures that the BiHashMap forms an equivalence class.
2018impl<T: BiHashItem + Eq, S: Clone + BuildHasher, A: Allocator> Eq
2019    for BiHashMap<T, S, A>
2020{
2021}
2022
2023fn detect_dup_or_insert<'a, A: Allocator>(
2024    item: hash_table::Entry<'a, usize, AllocWrapper<A>>,
2025    duplicates: &mut BTreeSet<usize>,
2026) -> Option<hash_table::VacantEntry<'a, usize, AllocWrapper<A>>> {
2027    match item {
2028        hash_table::Entry::Vacant(slot) => Some(slot),
2029        hash_table::Entry::Occupied(slot) => {
2030            duplicates.insert(*slot.get());
2031            None
2032        }
2033    }
2034}
2035
2036/// The `Extend` implementation overwrites duplicates. In the future, there will
2037/// also be an `extend_unique` method that will return an error.
2038///
2039/// # Examples
2040///
2041/// ```
2042/// # #[cfg(feature = "default-hasher")] {
2043/// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
2044///
2045/// #[derive(Debug, PartialEq, Eq)]
2046/// struct Item {
2047///     id: u32,
2048///     name: String,
2049///     value: i32,
2050/// }
2051///
2052/// impl BiHashItem for Item {
2053///     type K1<'a> = u32;
2054///     type K2<'a> = &'a str;
2055///
2056///     fn key1(&self) -> Self::K1<'_> {
2057///         self.id
2058///     }
2059///     fn key2(&self) -> Self::K2<'_> {
2060///         &self.name
2061///     }
2062///     bi_upcast!();
2063/// }
2064///
2065/// let mut map = BiHashMap::new();
2066/// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 }).unwrap();
2067///
2068/// let new_items = vec![
2069///     Item { id: 2, name: "bar".to_string(), value: 99 },
2070///     Item { id: 1, name: "baz".to_string(), value: 100 }, // overwrites existing
2071/// ];
2072///
2073/// map.extend(new_items);
2074/// assert_eq!(map.len(), 2);
2075/// assert_eq!(map.get1(&1).unwrap().name, "baz"); // overwritten
2076/// assert_eq!(map.get1(&1).unwrap().value, 100);
2077/// # }
2078/// ```
2079impl<T: BiHashItem, S: Clone + BuildHasher, A: Allocator> Extend<T>
2080    for BiHashMap<T, S, A>
2081{
2082    fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
2083        for item in iter {
2084            self.insert_overwrite(item);
2085        }
2086    }
2087}
2088
2089impl<'a, T: BiHashItem, S: Clone + BuildHasher, A: Allocator> IntoIterator
2090    for &'a BiHashMap<T, S, A>
2091{
2092    type Item = &'a T;
2093    type IntoIter = Iter<'a, T>;
2094
2095    #[inline]
2096    fn into_iter(self) -> Self::IntoIter {
2097        self.iter()
2098    }
2099}
2100
2101impl<'a, T: BiHashItem, S: Clone + BuildHasher, A: Allocator> IntoIterator
2102    for &'a mut BiHashMap<T, S, A>
2103{
2104    type Item = RefMut<'a, T, S>;
2105    type IntoIter = IterMut<'a, T, S, A>;
2106
2107    #[inline]
2108    fn into_iter(self) -> Self::IntoIter {
2109        self.iter_mut()
2110    }
2111}
2112
2113impl<T: BiHashItem, S: Clone + BuildHasher, A: Allocator> IntoIterator
2114    for BiHashMap<T, S, A>
2115{
2116    type Item = T;
2117    type IntoIter = IntoIter<T, A>;
2118
2119    #[inline]
2120    fn into_iter(self) -> Self::IntoIter {
2121        IntoIter::new(self.items)
2122    }
2123}
2124
2125/// The `FromIterator` implementation for `BiHashMap` overwrites duplicate
2126/// items.
2127///
2128/// # Examples
2129///
2130/// ```
2131/// # #[cfg(feature = "default-hasher")] {
2132/// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
2133///
2134/// #[derive(Debug, PartialEq, Eq)]
2135/// struct Item {
2136///     id: u32,
2137///     name: String,
2138///     value: i32,
2139/// }
2140///
2141/// impl BiHashItem for Item {
2142///     type K1<'a> = u32;
2143///     type K2<'a> = &'a str;
2144///
2145///     fn key1(&self) -> Self::K1<'_> {
2146///         self.id
2147///     }
2148///     fn key2(&self) -> Self::K2<'_> {
2149///         &self.name
2150///     }
2151///     bi_upcast!();
2152/// }
2153///
2154/// let items = vec![
2155///     Item { id: 1, name: "foo".to_string(), value: 42 },
2156///     Item { id: 2, name: "bar".to_string(), value: 99 },
2157///     Item { id: 1, name: "baz".to_string(), value: 100 }, // overwrites first item
2158/// ];
2159///
2160/// let map: BiHashMap<Item> = items.into_iter().collect();
2161/// assert_eq!(map.len(), 2);
2162/// assert_eq!(map.get1(&1).unwrap().name, "baz"); // overwritten
2163/// assert_eq!(map.get1(&1).unwrap().value, 100);
2164/// assert_eq!(map.get1(&2).unwrap().value, 99);
2165/// # }
2166/// ```
2167impl<T: BiHashItem, S: Clone + BuildHasher + Default, A: Default + Allocator>
2168    FromIterator<T> for BiHashMap<T, S, A>
2169{
2170    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
2171        let mut map = BiHashMap::default();
2172        for item in iter {
2173            map.insert_overwrite(item);
2174        }
2175        map
2176    }
2177}