Skip to main content

iddqd/bi_hash_map/
imp.rs

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