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