iddqd/tri_hash_map/
imp.rs

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