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