iddqd/tri_hash_map/
imp.rs

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