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