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