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.validate_structural(compactness)?;
1106
1107 // Check that the indexes are all correct.
1108 //
1109 // Unlike the structural checks, this re-looks up each key through the
1110 // user `Hash`, so it only holds when that `Hash` is lawful.
1111 for (ix, item) in self.items.iter() {
1112 let key1 = item.key1();
1113 let key2 = item.key2();
1114
1115 let Some(ix1) = self.find1_index(&key1) else {
1116 return Err(ValidationError::general(format!(
1117 "item at index {ix} has no key1 index"
1118 )));
1119 };
1120 let Some(ix2) = self.find2_index(&key2) else {
1121 return Err(ValidationError::general(format!(
1122 "item at index {ix} has no key2 index"
1123 )));
1124 };
1125
1126 if ix1 != ix || ix2 != ix {
1127 return Err(ValidationError::general(format!(
1128 "item at index {ix} has inconsistent indexes: {ix1}/{ix2}"
1129 )));
1130 }
1131 }
1132
1133 Ok(())
1134 }
1135
1136 /// Checks the structural invariants of the map:
1137 ///
1138 /// * The item set is well-formed.
1139 /// * Each per-key hash table holds exactly one entry per live item, with no
1140 /// duplicate `ItemIndex`es.
1141 ///
1142 /// Unlike [`validate`](Self::validate), this does not re-look-up keys
1143 /// through the user `Hash`, so it holds regardless of whether that `Hash`
1144 /// is lawful. A buggy hasher can desync the logical key→item mapping, but
1145 /// it must never break these structural invariants! Doing so would be
1146 /// unsoundness, e.g. duplicate indexes enabling mutable aliasing.
1147 #[doc(hidden)]
1148 pub fn validate_structural(
1149 &self,
1150 compactness: ValidateCompact,
1151 ) -> Result<(), ValidationError> {
1152 self.items.validate(compactness)?;
1153 self.tables.validate(self.len(), compactness)?;
1154 Ok(())
1155 }
1156
1157 /// Inserts a value into the map, removing any conflicting items and
1158 /// returning a list of those items.
1159 ///
1160 /// # Examples
1161 ///
1162 /// ```
1163 /// # #[cfg(feature = "default-hasher")] {
1164 /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
1165 ///
1166 /// #[derive(Debug, PartialEq, Eq)]
1167 /// struct Item {
1168 /// id: u32,
1169 /// name: String,
1170 /// value: i32,
1171 /// }
1172 ///
1173 /// impl BiHashItem for Item {
1174 /// type K1<'a> = u32;
1175 /// type K2<'a> = &'a str;
1176 ///
1177 /// fn key1(&self) -> Self::K1<'_> {
1178 /// self.id
1179 /// }
1180 /// fn key2(&self) -> Self::K2<'_> {
1181 /// &self.name
1182 /// }
1183 /// bi_upcast!();
1184 /// }
1185 ///
1186 /// let mut map = BiHashMap::new();
1187 /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
1188 /// .unwrap();
1189 /// map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
1190 /// .unwrap();
1191 ///
1192 /// // Insert an item with conflicting key1
1193 /// let removed = map.insert_overwrite(Item {
1194 /// id: 1,
1195 /// name: "baz".to_string(),
1196 /// value: 100,
1197 /// });
1198 /// assert_eq!(removed.len(), 1);
1199 /// assert_eq!(removed[0].name, "foo");
1200 /// assert_eq!(removed[0].value, 42);
1201 ///
1202 /// assert_eq!(map.len(), 2);
1203 /// assert_eq!(map.get1(&1).unwrap().name, "baz");
1204 /// # }
1205 /// ```
1206 #[doc(alias = "insert")]
1207 pub fn insert_overwrite(&mut self, value: T) -> Vec<T> {
1208 let prepared = self.prepare_insert_overwrite(&value);
1209
1210 let mut duplicates = Vec::with_capacity(prepared.duplicate_count());
1211
1212 self.try_reserve_insert_overwrite_commit(
1213 prepared.needs_new_item_slot(),
1214 )
1215 .expect("reserved space successfully");
1216
1217 self.commit_insert_overwrite(value, prepared, &mut duplicates);
1218
1219 duplicates
1220 }
1221
1222 /// Inserts a value into the set, returning an error if any duplicates were
1223 /// added.
1224 ///
1225 /// # Examples
1226 ///
1227 /// ```
1228 /// # #[cfg(feature = "default-hasher")] {
1229 /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
1230 ///
1231 /// #[derive(Debug, PartialEq, Eq)]
1232 /// struct Item {
1233 /// id: u32,
1234 /// name: String,
1235 /// value: i32,
1236 /// }
1237 ///
1238 /// impl BiHashItem for Item {
1239 /// type K1<'a> = u32;
1240 /// type K2<'a> = &'a str;
1241 ///
1242 /// fn key1(&self) -> Self::K1<'_> {
1243 /// self.id
1244 /// }
1245 /// fn key2(&self) -> Self::K2<'_> {
1246 /// &self.name
1247 /// }
1248 /// bi_upcast!();
1249 /// }
1250 ///
1251 /// let mut map = BiHashMap::new();
1252 ///
1253 /// // Successful insertion
1254 /// assert!(
1255 /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
1256 /// .is_ok()
1257 /// );
1258 /// assert!(
1259 /// map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
1260 /// .is_ok()
1261 /// );
1262 ///
1263 /// // Duplicate key1
1264 /// assert!(
1265 /// map.insert_unique(Item { id: 1, name: "baz".to_string(), value: 100 })
1266 /// .is_err()
1267 /// );
1268 ///
1269 /// // Duplicate key2
1270 /// assert!(
1271 /// map.insert_unique(Item { id: 3, name: "foo".to_string(), value: 200 })
1272 /// .is_err()
1273 /// );
1274 /// # }
1275 /// ```
1276 pub fn insert_unique(
1277 &mut self,
1278 value: T,
1279 ) -> Result<(), DuplicateItem<T, &T>> {
1280 let _ = self.insert_unique_impl(value)?;
1281 Ok(())
1282 }
1283
1284 /// Returns true if the map contains a single item that matches both `key1` and `key2`.
1285 ///
1286 /// # Examples
1287 ///
1288 /// ```
1289 /// # #[cfg(feature = "default-hasher")] {
1290 /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
1291 ///
1292 /// #[derive(Debug, PartialEq, Eq)]
1293 /// struct Item {
1294 /// id: u32,
1295 /// name: String,
1296 /// value: i32,
1297 /// }
1298 ///
1299 /// impl BiHashItem for Item {
1300 /// type K1<'a> = u32;
1301 /// type K2<'a> = &'a str;
1302 ///
1303 /// fn key1(&self) -> Self::K1<'_> {
1304 /// self.id
1305 /// }
1306 /// fn key2(&self) -> Self::K2<'_> {
1307 /// &self.name
1308 /// }
1309 /// bi_upcast!();
1310 /// }
1311 ///
1312 /// let mut map = BiHashMap::new();
1313 /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 }).unwrap();
1314 /// map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 }).unwrap();
1315 ///
1316 /// assert!(map.contains_key_unique(&1, &"foo"));
1317 /// assert!(map.contains_key_unique(&2, &"bar"));
1318 /// assert!(!map.contains_key_unique(&1, &"bar")); // key1 exists but key2 doesn't match
1319 /// assert!(!map.contains_key_unique(&3, &"baz")); // neither key exists
1320 /// # }
1321 /// ```
1322 pub fn contains_key_unique<'a, Q1, Q2>(
1323 &'a self,
1324 key1: &Q1,
1325 key2: &Q2,
1326 ) -> bool
1327 where
1328 Q1: Hash + Equivalent<T::K1<'a>> + ?Sized,
1329 Q2: Hash + Equivalent<T::K2<'a>> + ?Sized,
1330 {
1331 self.get_unique(key1, key2).is_some()
1332 }
1333
1334 /// Gets a reference to the unique item associated with the given `key1` and
1335 /// `key2`, if it exists.
1336 ///
1337 /// # Examples
1338 ///
1339 /// ```
1340 /// # #[cfg(feature = "default-hasher")] {
1341 /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
1342 ///
1343 /// #[derive(Debug, PartialEq, Eq)]
1344 /// struct Item {
1345 /// id: u32,
1346 /// name: String,
1347 /// value: i32,
1348 /// }
1349 ///
1350 /// impl BiHashItem for Item {
1351 /// type K1<'a> = u32;
1352 /// type K2<'a> = &'a str;
1353 ///
1354 /// fn key1(&self) -> Self::K1<'_> {
1355 /// self.id
1356 /// }
1357 /// fn key2(&self) -> Self::K2<'_> {
1358 /// &self.name
1359 /// }
1360 /// bi_upcast!();
1361 /// }
1362 ///
1363 /// let mut map = BiHashMap::new();
1364 /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 }).unwrap();
1365 /// map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 }).unwrap();
1366 ///
1367 /// assert_eq!(map.get_unique(&1, &"foo").unwrap().value, 42);
1368 /// assert_eq!(map.get_unique(&2, &"bar").unwrap().value, 99);
1369 /// assert!(map.get_unique(&1, &"bar").is_none()); // key1 exists but key2 doesn't match
1370 /// assert!(map.get_unique(&3, &"baz").is_none()); // neither key exists
1371 /// # }
1372 /// ```
1373 pub fn get_unique<'a, Q1, Q2>(
1374 &'a self,
1375 key1: &Q1,
1376 key2: &Q2,
1377 ) -> Option<&'a T>
1378 where
1379 Q1: Hash + Equivalent<T::K1<'a>> + ?Sized,
1380 Q2: Hash + Equivalent<T::K2<'a>> + ?Sized,
1381 {
1382 let index = self.find1_index(key1)?;
1383 let item = &self.items[index];
1384 if key2.equivalent(&item.key2()) { Some(item) } else { None }
1385 }
1386
1387 /// Gets a mutable reference to the unique item associated with the given
1388 /// `key1` and `key2`, if it exists.
1389 pub fn get_mut_unique<'a, Q1, Q2>(
1390 &'a mut self,
1391 key1: &Q1,
1392 key2: &Q2,
1393 ) -> Option<RefMut<'a, T, S>>
1394 where
1395 Q1: Hash + Equivalent<T::K1<'a>> + ?Sized,
1396 Q2: Hash + Equivalent<T::K2<'a>> + ?Sized,
1397 {
1398 let (dormant_map, index) = {
1399 let (map, dormant_map) = DormantMutRef::new(self);
1400 let index = map.find1_index(key1)?;
1401 // Check key2 match before proceeding
1402 if !key2.equivalent(&map.items[index].key2()) {
1403 return None;
1404 }
1405 (dormant_map, index)
1406 };
1407
1408 // SAFETY: `map` is not used after this point.
1409 let awakened_map = unsafe { dormant_map.awaken() };
1410 let item = &mut awakened_map.items[index];
1411 let state = awakened_map.tables.state.clone();
1412 let hashes =
1413 awakened_map.tables.make_hashes::<T>(&item.key1(), &item.key2());
1414 Some(RefMut::new(state, hashes, item))
1415 }
1416
1417 /// Removes the item uniquely identified by `key1` and `key2`, if it exists.
1418 pub fn remove_unique<'a, Q1, Q2>(
1419 &'a mut self,
1420 key1: &Q1,
1421 key2: &Q2,
1422 ) -> Option<T>
1423 where
1424 Q1: Hash + Equivalent<T::K1<'a>> + ?Sized,
1425 Q2: Hash + Equivalent<T::K2<'a>> + ?Sized,
1426 {
1427 let (dormant_map, remove_index) = {
1428 let (map, dormant_map) = DormantMutRef::new(self);
1429 let remove_index = map.find1_index(key1)?;
1430 if !key2.equivalent(&map.items[remove_index].key2()) {
1431 return None;
1432 }
1433 (dormant_map, remove_index)
1434 };
1435
1436 // SAFETY: `map` is not used after this point.
1437 let awakened_map = unsafe { dormant_map.awaken() };
1438
1439 awakened_map.remove_by_index(remove_index)
1440 }
1441
1442 /// Returns true if the map contains the given `key1`.
1443 ///
1444 /// # Examples
1445 ///
1446 /// ```
1447 /// # #[cfg(feature = "default-hasher")] {
1448 /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
1449 ///
1450 /// #[derive(Debug, PartialEq, Eq)]
1451 /// struct Item {
1452 /// id: u32,
1453 /// name: String,
1454 /// value: i32,
1455 /// }
1456 ///
1457 /// impl BiHashItem for Item {
1458 /// type K1<'a> = u32;
1459 /// type K2<'a> = &'a str;
1460 ///
1461 /// fn key1(&self) -> Self::K1<'_> {
1462 /// self.id
1463 /// }
1464 /// fn key2(&self) -> Self::K2<'_> {
1465 /// &self.name
1466 /// }
1467 /// bi_upcast!();
1468 /// }
1469 ///
1470 /// let mut map = BiHashMap::new();
1471 /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
1472 /// .unwrap();
1473 /// map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
1474 /// .unwrap();
1475 ///
1476 /// assert!(map.contains_key1(&1));
1477 /// assert!(map.contains_key1(&2));
1478 /// assert!(!map.contains_key1(&3));
1479 /// # }
1480 /// ```
1481 pub fn contains_key1<'a, Q>(&'a self, key1: &Q) -> bool
1482 where
1483 Q: Hash + Equivalent<T::K1<'a>> + ?Sized,
1484 {
1485 self.find1_index(key1).is_some()
1486 }
1487
1488 /// Gets a reference to the value associated with the given `key1`.
1489 ///
1490 /// # Examples
1491 ///
1492 /// ```
1493 /// # #[cfg(feature = "default-hasher")] {
1494 /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
1495 ///
1496 /// #[derive(Debug, PartialEq, Eq)]
1497 /// struct Item {
1498 /// id: u32,
1499 /// name: String,
1500 /// value: i32,
1501 /// }
1502 ///
1503 /// impl BiHashItem for Item {
1504 /// type K1<'a> = u32;
1505 /// type K2<'a> = &'a str;
1506 ///
1507 /// fn key1(&self) -> Self::K1<'_> {
1508 /// self.id
1509 /// }
1510 /// fn key2(&self) -> Self::K2<'_> {
1511 /// &self.name
1512 /// }
1513 /// bi_upcast!();
1514 /// }
1515 ///
1516 /// let mut map = BiHashMap::new();
1517 /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
1518 /// .unwrap();
1519 /// map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
1520 /// .unwrap();
1521 ///
1522 /// assert_eq!(map.get1(&1).unwrap().value, 42);
1523 /// assert_eq!(map.get1(&2).unwrap().value, 99);
1524 /// assert!(map.get1(&3).is_none());
1525 /// # }
1526 /// ```
1527 pub fn get1<'a, Q>(&'a self, key1: &Q) -> Option<&'a T>
1528 where
1529 Q: Hash + Equivalent<T::K1<'a>> + ?Sized,
1530 {
1531 self.find1(key1)
1532 }
1533
1534 /// Gets a mutable reference to the value associated with the given `key1`.
1535 pub fn get1_mut<'a, Q>(&'a mut self, key1: &Q) -> Option<RefMut<'a, T, S>>
1536 where
1537 Q: Hash + Equivalent<T::K1<'a>> + ?Sized,
1538 {
1539 let (dormant_map, index) = {
1540 let (map, dormant_map) = DormantMutRef::new(self);
1541 let index = map.find1_index(key1)?;
1542 (dormant_map, index)
1543 };
1544
1545 // SAFETY: `map` is not used after this point.
1546 let awakened_map = unsafe { dormant_map.awaken() };
1547 let item = &mut awakened_map.items[index];
1548 let state = awakened_map.tables.state.clone();
1549 let hashes =
1550 awakened_map.tables.make_hashes::<T>(&item.key1(), &item.key2());
1551 Some(RefMut::new(state, hashes, item))
1552 }
1553
1554 /// Removes an item from the map by its `key1`.
1555 ///
1556 /// # Examples
1557 ///
1558 /// ```
1559 /// # #[cfg(feature = "default-hasher")] {
1560 /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
1561 ///
1562 /// #[derive(Debug, PartialEq, Eq)]
1563 /// struct Item {
1564 /// id: u32,
1565 /// name: String,
1566 /// value: i32,
1567 /// }
1568 ///
1569 /// impl BiHashItem for Item {
1570 /// type K1<'a> = u32;
1571 /// type K2<'a> = &'a str;
1572 ///
1573 /// fn key1(&self) -> Self::K1<'_> {
1574 /// self.id
1575 /// }
1576 /// fn key2(&self) -> Self::K2<'_> {
1577 /// &self.name
1578 /// }
1579 /// bi_upcast!();
1580 /// }
1581 ///
1582 /// let mut map = BiHashMap::new();
1583 /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
1584 /// .unwrap();
1585 /// map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
1586 /// .unwrap();
1587 ///
1588 /// let removed = map.remove1(&1);
1589 /// assert_eq!(removed.unwrap().value, 42);
1590 /// assert_eq!(map.len(), 1);
1591 /// assert!(map.get1(&1).is_none());
1592 /// assert!(map.remove1(&3).is_none());
1593 /// # }
1594 /// ```
1595 pub fn remove1<'a, Q>(&'a mut self, key1: &Q) -> Option<T>
1596 where
1597 Q: Hash + Equivalent<T::K1<'a>> + ?Sized,
1598 {
1599 let (dormant_map, remove_index) = {
1600 let (map, dormant_map) = DormantMutRef::new(self);
1601 let remove_index = map.find1_index(key1)?;
1602 (dormant_map, remove_index)
1603 };
1604
1605 // SAFETY: `map` is not used after this point.
1606 let awakened_map = unsafe { dormant_map.awaken() };
1607
1608 awakened_map.remove_by_index(remove_index)
1609 }
1610
1611 /// Returns true if the map contains the given `key2`.
1612 ///
1613 /// # Examples
1614 ///
1615 /// ```
1616 /// # #[cfg(feature = "default-hasher")] {
1617 /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
1618 ///
1619 /// #[derive(Debug, PartialEq, Eq)]
1620 /// struct Item {
1621 /// id: u32,
1622 /// name: String,
1623 /// value: i32,
1624 /// }
1625 ///
1626 /// impl BiHashItem for Item {
1627 /// type K1<'a> = u32;
1628 /// type K2<'a> = &'a str;
1629 ///
1630 /// fn key1(&self) -> Self::K1<'_> {
1631 /// self.id
1632 /// }
1633 /// fn key2(&self) -> Self::K2<'_> {
1634 /// &self.name
1635 /// }
1636 /// bi_upcast!();
1637 /// }
1638 ///
1639 /// let mut map = BiHashMap::new();
1640 /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
1641 /// .unwrap();
1642 /// map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
1643 /// .unwrap();
1644 ///
1645 /// assert!(map.contains_key2(&"foo"));
1646 /// assert!(map.contains_key2(&"bar"));
1647 /// assert!(!map.contains_key2(&"baz"));
1648 /// # }
1649 /// ```
1650 pub fn contains_key2<'a, Q>(&'a self, key2: &Q) -> bool
1651 where
1652 Q: Hash + Equivalent<T::K2<'a>> + ?Sized,
1653 {
1654 self.find2_index(key2).is_some()
1655 }
1656
1657 /// Gets a reference to the value associated with the given `key2`.
1658 ///
1659 /// # Examples
1660 ///
1661 /// ```
1662 /// # #[cfg(feature = "default-hasher")] {
1663 /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
1664 ///
1665 /// #[derive(Debug, PartialEq, Eq)]
1666 /// struct Item {
1667 /// id: u32,
1668 /// name: String,
1669 /// value: i32,
1670 /// }
1671 ///
1672 /// impl BiHashItem for Item {
1673 /// type K1<'a> = u32;
1674 /// type K2<'a> = &'a str;
1675 ///
1676 /// fn key1(&self) -> Self::K1<'_> {
1677 /// self.id
1678 /// }
1679 /// fn key2(&self) -> Self::K2<'_> {
1680 /// &self.name
1681 /// }
1682 /// bi_upcast!();
1683 /// }
1684 ///
1685 /// let mut map = BiHashMap::new();
1686 /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
1687 /// .unwrap();
1688 /// map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
1689 /// .unwrap();
1690 ///
1691 /// assert_eq!(map.get2(&"foo").unwrap().value, 42);
1692 /// assert_eq!(map.get2(&"bar").unwrap().value, 99);
1693 /// assert!(map.get2(&"baz").is_none());
1694 /// # }
1695 /// ```
1696 pub fn get2<'a, Q>(&'a self, key2: &Q) -> Option<&'a T>
1697 where
1698 Q: Hash + Equivalent<T::K2<'a>> + ?Sized,
1699 {
1700 self.find2(key2)
1701 }
1702
1703 /// Gets a mutable reference to the value associated with the given `key2`.
1704 ///
1705 /// # Examples
1706 ///
1707 /// ```
1708 /// # #[cfg(feature = "default-hasher")] {
1709 /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
1710 ///
1711 /// #[derive(Debug, PartialEq, Eq)]
1712 /// struct Item {
1713 /// id: u32,
1714 /// name: String,
1715 /// value: i32,
1716 /// }
1717 ///
1718 /// impl BiHashItem for Item {
1719 /// type K1<'a> = u32;
1720 /// type K2<'a> = &'a str;
1721 ///
1722 /// fn key1(&self) -> Self::K1<'_> {
1723 /// self.id
1724 /// }
1725 /// fn key2(&self) -> Self::K2<'_> {
1726 /// &self.name
1727 /// }
1728 /// bi_upcast!();
1729 /// }
1730 ///
1731 /// let mut map = BiHashMap::new();
1732 /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
1733 /// .unwrap();
1734 ///
1735 /// if let Some(mut item_ref) = map.get2_mut(&"foo") {
1736 /// item_ref.value = 100;
1737 /// }
1738 ///
1739 /// assert_eq!(map.get2(&"foo").unwrap().value, 100);
1740 /// # }
1741 /// ```
1742 pub fn get2_mut<'a, Q>(&'a mut self, key2: &Q) -> Option<RefMut<'a, T, S>>
1743 where
1744 Q: Hash + Equivalent<T::K2<'a>> + ?Sized,
1745 {
1746 let (dormant_map, index) = {
1747 let (map, dormant_map) = DormantMutRef::new(self);
1748 let index = map.find2_index(key2)?;
1749 (dormant_map, index)
1750 };
1751
1752 // SAFETY: `map` is not used after this point.
1753 let awakened_map = unsafe { dormant_map.awaken() };
1754 let item = &mut awakened_map.items[index];
1755 let state = awakened_map.tables.state.clone();
1756 let hashes =
1757 awakened_map.tables.make_hashes::<T>(&item.key1(), &item.key2());
1758 Some(RefMut::new(state, hashes, item))
1759 }
1760
1761 /// Removes an item from the map by its `key2`.
1762 ///
1763 /// # Examples
1764 ///
1765 /// ```
1766 /// # #[cfg(feature = "default-hasher")] {
1767 /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
1768 ///
1769 /// #[derive(Debug, PartialEq, Eq)]
1770 /// struct Item {
1771 /// id: u32,
1772 /// name: String,
1773 /// value: i32,
1774 /// }
1775 ///
1776 /// impl BiHashItem for Item {
1777 /// type K1<'a> = u32;
1778 /// type K2<'a> = &'a str;
1779 ///
1780 /// fn key1(&self) -> Self::K1<'_> {
1781 /// self.id
1782 /// }
1783 /// fn key2(&self) -> Self::K2<'_> {
1784 /// &self.name
1785 /// }
1786 /// bi_upcast!();
1787 /// }
1788 ///
1789 /// let mut map = BiHashMap::new();
1790 /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
1791 /// .unwrap();
1792 /// map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
1793 /// .unwrap();
1794 ///
1795 /// let removed = map.remove2(&"foo");
1796 /// assert_eq!(removed.unwrap().value, 42);
1797 /// assert_eq!(map.len(), 1);
1798 /// assert!(map.get2(&"foo").is_none());
1799 /// assert!(map.remove2(&"baz").is_none());
1800 /// # }
1801 /// ```
1802 pub fn remove2<'a, Q>(&'a mut self, key2: &Q) -> Option<T>
1803 where
1804 Q: Hash + Equivalent<T::K2<'a>> + ?Sized,
1805 {
1806 let (dormant_map, remove_index) = {
1807 let (map, dormant_map) = DormantMutRef::new(self);
1808 let remove_index = map.find2_index(key2)?;
1809 (dormant_map, remove_index)
1810 };
1811
1812 // SAFETY: `map` is not used after this point.
1813 let awakened_map = unsafe { dormant_map.awaken() };
1814
1815 awakened_map.remove_by_index(remove_index)
1816 }
1817
1818 /// Retrieves an entry by its keys.
1819 ///
1820 /// Due to borrow checker limitations, this always accepts owned keys rather
1821 /// than a borrowed form of them.
1822 ///
1823 /// # Differences from single-key entries
1824 ///
1825 /// The [`Entry`] returned by this method differs from those provided
1826 /// for the other map types, because it is possible for one of the two keys
1827 /// provided to correspond to an existing entry, while the other does not.
1828 ///
1829 /// For more information, and examples covering non-unique entries, see the
1830 /// type-level documentation for [`Entry`].
1831 ///
1832 /// # Examples
1833 ///
1834 /// ```
1835 /// # #[cfg(feature = "default-hasher")] {
1836 /// use iddqd::{BiHashItem, BiHashMap, bi_hash_map, bi_upcast};
1837 ///
1838 /// #[derive(Debug, PartialEq, Eq)]
1839 /// struct Item {
1840 /// id: u32,
1841 /// name: String,
1842 /// value: i32,
1843 /// }
1844 ///
1845 /// impl BiHashItem for Item {
1846 /// type K1<'a> = u32;
1847 /// type K2<'a> = &'a str;
1848 ///
1849 /// fn key1(&self) -> Self::K1<'_> {
1850 /// self.id
1851 /// }
1852 /// fn key2(&self) -> Self::K2<'_> {
1853 /// &self.name
1854 /// }
1855 /// bi_upcast!();
1856 /// }
1857 ///
1858 /// let mut map = BiHashMap::new();
1859 /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
1860 /// .unwrap();
1861 ///
1862 /// // Get an existing entry.
1863 /// match map.entry(1, "foo") {
1864 /// bi_hash_map::Entry::Occupied(entry) => {
1865 /// assert_eq!(entry.get().as_unique().unwrap().value, 42);
1866 /// }
1867 /// bi_hash_map::Entry::Vacant(_) => panic!("Should be occupied"),
1868 /// }
1869 ///
1870 /// // Try to get a non-existing entry.
1871 /// match map.entry(2, "bar") {
1872 /// bi_hash_map::Entry::Occupied(_) => panic!("Should be vacant"),
1873 /// bi_hash_map::Entry::Vacant(entry) => {
1874 /// entry.insert(Item { id: 2, name: "bar".to_string(), value: 99 });
1875 /// }
1876 /// }
1877 ///
1878 /// assert_eq!(map.len(), 2);
1879 /// # }
1880 /// ```
1881 ///
1882 /// For an expanded example, see the type-level documentation for [`Entry`].
1883 pub fn entry<'a>(
1884 &'a mut self,
1885 key1: T::K1<'_>,
1886 key2: T::K2<'_>,
1887 ) -> Entry<'a, T, S, A> {
1888 // Why does this always take owned keys? Well, it would seem like we
1889 // should be able to pass in any Q1 and Q2 that are equivalent. That
1890 // results in *this* code compiling fine, but callers have trouble using
1891 // it because the borrow checker believes the keys are borrowed for the
1892 // full 'a rather than a shorter lifetime.
1893 //
1894 // By accepting owned keys, we can use the upcast functions to convert
1895 // them to a shorter lifetime (so this function accepts T::K1<'_> rather
1896 // than T::K1<'a>).
1897 //
1898 // Really, the solution here is to allow GATs to require covariant
1899 // parameters. If that were allowed, the borrow checker should be able
1900 // to figure out that keys don't need to be borrowed for the full 'a,
1901 // just for some shorter lifetime.
1902 let (map, dormant_map) = DormantMutRef::new(self);
1903 let key1 = T::upcast_key1(key1);
1904 let key2 = T::upcast_key2(key2);
1905 let (index1, index2) = {
1906 // index1 and index2 are explicitly typed to show that it has a
1907 // trivial Drop impl that doesn't capture anything from map.
1908 let index1: Option<ItemIndex> = map.tables.k1_to_item.find_index(
1909 &map.tables.state,
1910 &key1,
1911 |index| map.items[index].key1(),
1912 );
1913 let index2: Option<ItemIndex> = map.tables.k2_to_item.find_index(
1914 &map.tables.state,
1915 &key2,
1916 |index| map.items[index].key2(),
1917 );
1918 (index1, index2)
1919 };
1920
1921 match (index1, index2) {
1922 (Some(index1), Some(index2)) if index1 == index2 => {
1923 // The item is already in the map.
1924 drop(key1);
1925 Entry::Occupied(
1926 // SAFETY: `map` is not used after this point.
1927 unsafe {
1928 OccupiedEntry::new(
1929 dormant_map,
1930 EntryIndexes::Unique(index1),
1931 )
1932 },
1933 )
1934 }
1935 (None, None) => {
1936 let hashes = map.tables.make_hashes::<T>(&key1, &key2);
1937 Entry::Vacant(
1938 // SAFETY: `map` is not used after this point.
1939 unsafe { VacantEntry::new(dormant_map, hashes) },
1940 )
1941 }
1942 (index1, index2) => Entry::Occupied(
1943 // SAFETY: `map` is not used after this point.
1944 unsafe {
1945 OccupiedEntry::new(
1946 dormant_map,
1947 EntryIndexes::NonUnique { index1, index2 },
1948 )
1949 },
1950 ),
1951 }
1952 }
1953
1954 /// Retains only the elements specified by the predicate.
1955 ///
1956 /// In other words, remove all items `T` for which `f(RefMut<T>)` returns
1957 /// false. The elements are visited in an arbitrary order.
1958 ///
1959 /// # Examples
1960 ///
1961 /// ```
1962 /// # #[cfg(feature = "default-hasher")] {
1963 /// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
1964 ///
1965 /// #[derive(Debug, PartialEq, Eq, Hash)]
1966 /// struct Item {
1967 /// id: u32,
1968 /// name: String,
1969 /// value: u32,
1970 /// }
1971 ///
1972 /// impl BiHashItem for Item {
1973 /// type K1<'a> = u32;
1974 /// type K2<'a> = &'a str;
1975 ///
1976 /// fn key1(&self) -> Self::K1<'_> {
1977 /// self.id
1978 /// }
1979 /// fn key2(&self) -> Self::K2<'_> {
1980 /// &self.name
1981 /// }
1982 ///
1983 /// bi_upcast!();
1984 /// }
1985 ///
1986 /// let mut map = BiHashMap::new();
1987 /// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
1988 /// .unwrap();
1989 /// map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 20 })
1990 /// .unwrap();
1991 /// map.insert_unique(Item { id: 3, name: "baz".to_string(), value: 99 })
1992 /// .unwrap();
1993 ///
1994 /// // Retain only items where value is greater than 30
1995 /// map.retain(|item| item.value > 30);
1996 ///
1997 /// assert_eq!(map.len(), 2);
1998 /// assert_eq!(map.get1(&1).unwrap().value, 42);
1999 /// assert_eq!(map.get1(&3).unwrap().value, 99);
2000 /// assert!(map.get1(&2).is_none());
2001 /// # }
2002 /// ```
2003 pub fn retain<'a, F>(&'a mut self, mut f: F)
2004 where
2005 F: for<'b> FnMut(RefMut<'b, T, S>) -> bool,
2006 {
2007 let hash_state = self.tables.state.clone();
2008 let (_, mut dormant_items) = DormantMutRef::new(&mut self.items);
2009 let mut removed_item = None;
2010
2011 self.tables.k1_to_item.retain(|index| {
2012 // Drop the previously-removed item here, at the top of the next
2013 // iteration.
2014 //
2015 // By now, the prior `k1_to_item` entry has been erased, so if
2016 // `drop` below panics, `k1_to_item`, `k2_to_item`, and `items`
2017 // remain in sync. Dropping the item at the end of the prior
2018 // iteration would unwind before the table erased the entry, leaving
2019 // `k1_to_item` pointing at a slot we already removed from `items`
2020 // and `k2_to_item`.
2021 drop(removed_item.take());
2022
2023 let (item, dormant_items) = {
2024 // SAFETY: All uses of `items` ended in the previous iteration.
2025 let items = unsafe { dormant_items.reborrow() };
2026 let (items, dormant_items) = DormantMutRef::new(items);
2027 let item: &'a mut T = items
2028 .get_mut(index)
2029 .expect("all indexes are present in self.items");
2030 (item, dormant_items)
2031 };
2032
2033 let (hashes, dormant_item) = {
2034 let (item, dormant_item): (&'a mut T, _) =
2035 DormantMutRef::new(item);
2036 // Use T::k1(item) rather than item.key() to force the key
2037 // trait function to be called for T rather than &mut T.
2038 let key1 = T::key1(item);
2039 let key2 = T::key2(item);
2040 let hash1 = hash_state.hash_one(key1);
2041 let hash2 = hash_state.hash_one(key2);
2042 ([MapHash::new(hash1), MapHash::new(hash2)], dormant_item)
2043 };
2044
2045 let hash2 = hashes[1].hash();
2046 let retain = {
2047 // SAFETY: The original item is no longer used after the second
2048 // block above. dormant_items, from which item is derived, is
2049 // currently dormant.
2050 let item = unsafe { dormant_item.awaken() };
2051
2052 let ref_mut = RefMut::new(hash_state.clone(), hashes, item);
2053 f(ref_mut)
2054 };
2055
2056 if retain {
2057 true
2058 } else {
2059 let k2_entry = self
2060 .tables
2061 .k2_to_item
2062 .find_entry_by_hash(hash2, |map2_index| {
2063 map2_index == index
2064 });
2065 match k2_entry {
2066 Ok(entry) => {
2067 entry.remove();
2068 }
2069 Err(_) => {
2070 self.tables.k2_to_item.remove_by_index(index);
2071 }
2072 }
2073
2074 // SAFETY: The original items is no longer used after the first
2075 // block above, and item + dormant_item have been dropped after
2076 // being used above. The k2 work between them borrows only
2077 // `self.tables.k2_to_item`, which is disjoint from
2078 // `self.items`.
2079 let items = unsafe { dormant_items.awaken() };
2080 removed_item = Some(
2081 items
2082 .remove(index)
2083 .expect("all indexes are present in self.items"),
2084 );
2085
2086 false
2087 }
2088 });
2089
2090 // Anything in `removed_item` is implicitly dropped now.
2091 }
2092
2093 fn find1<'a, Q>(&'a self, k: &Q) -> Option<&'a T>
2094 where
2095 Q: Hash + Equivalent<T::K1<'a>> + ?Sized,
2096 {
2097 self.find1_index(k).map(|ix| &self.items[ix])
2098 }
2099
2100 fn find1_index<'a, Q>(&'a self, k: &Q) -> Option<ItemIndex>
2101 where
2102 Q: Hash + Equivalent<T::K1<'a>> + ?Sized,
2103 {
2104 self.tables
2105 .k1_to_item
2106 .find_index(&self.tables.state, k, |index| self.items[index].key1())
2107 }
2108
2109 fn find2<'a, Q>(&'a self, k: &Q) -> Option<&'a T>
2110 where
2111 Q: Hash + Equivalent<T::K2<'a>> + ?Sized,
2112 {
2113 self.find2_index(k).map(|ix| &self.items[ix])
2114 }
2115
2116 fn find2_index<'a, Q>(&'a self, k: &Q) -> Option<ItemIndex>
2117 where
2118 Q: Hash + Equivalent<T::K2<'a>> + ?Sized,
2119 {
2120 self.tables
2121 .k2_to_item
2122 .find_index(&self.tables.state, k, |index| self.items[index].key2())
2123 }
2124
2125 fn prepare_insert_overwrite(&self, value: &T) -> PreparedInsertOverwrite {
2126 let key1 = value.key1();
2127 let key2 = value.key2();
2128
2129 let index1 = self.find1_index(&key1);
2130 let index2 = self.find2_index(&key2);
2131 let hashes = self.tables.make_hashes::<T>(&key1, &key2);
2132
2133 let duplicates =
2134 PreparedDuplicate::from_indexes([index1, index2], |index| {
2135 self.prepare_duplicate(index)
2136 });
2137
2138 PreparedInsertOverwrite { index1, index2, duplicates, hashes }
2139 }
2140
2141 fn prepare_entry_index_removal(
2142 &self,
2143 indexes: EntryIndexes,
2144 ) -> Vec<PreparedDuplicate> {
2145 match indexes {
2146 EntryIndexes::Unique(index) => {
2147 PreparedDuplicate::from_indexes([Some(index)], |index| {
2148 self.prepare_duplicate(index)
2149 })
2150 }
2151 EntryIndexes::NonUnique { index1, index2 } => {
2152 PreparedDuplicate::from_indexes([index1, index2], |index| {
2153 self.prepare_duplicate(index)
2154 })
2155 }
2156 }
2157 }
2158
2159 fn prepare_duplicate(&self, index: ItemIndex) -> PreparedDuplicate {
2160 let item = &self.items[index];
2161 let key1 = item.key1();
2162 let key2 = item.key2();
2163 let hashes = self.tables.make_hashes::<T>(&key1, &key2);
2164
2165 PreparedDuplicate { index, hashes }
2166 }
2167
2168 fn try_reserve_insert_overwrite_commit(
2169 &mut self,
2170 needs_new_item_slot: bool,
2171 ) -> Result<(), TryReserveError> {
2172 if needs_new_item_slot {
2173 self.items.try_reserve(1)?;
2174 }
2175
2176 self.tables
2177 .k1_to_item
2178 .try_reserve(1)
2179 .map_err(TryReserveError::from_hashbrown)?;
2180 self.tables
2181 .k2_to_item
2182 .try_reserve(1)
2183 .map_err(TryReserveError::from_hashbrown)?;
2184
2185 Ok(())
2186 }
2187
2188 fn commit_insert_overwrite(
2189 &mut self,
2190 value: T,
2191 prepared: PreparedInsertOverwrite,
2192 duplicates: &mut Vec<T>,
2193 ) -> ItemIndex {
2194 // From here until insertion completes, do not call user code or
2195 // allocate. The caller prepared hashes/indexes and reserved capacity.
2196 for duplicate in prepared.duplicates {
2197 duplicates.push(
2198 self.remove_duplicate(duplicate)
2199 .expect("duplicate index was prepared"),
2200 );
2201 }
2202
2203 self.insert_unique_with_prepared_hashes(value, prepared.hashes)
2204 }
2205
2206 fn insert_unique_with_prepared_hashes(
2207 &mut self,
2208 value: T,
2209 hashes: [MapHash; 2],
2210 ) -> ItemIndex {
2211 let [hash1, hash2] = hashes;
2212 let next_index = self.items.assert_can_grow().insert(value);
2213
2214 self.tables.k1_to_item.insert_prehashed_unchecked(hash1, next_index);
2215 self.tables.k2_to_item.insert_prehashed_unchecked(hash2, next_index);
2216
2217 next_index
2218 }
2219
2220 pub(super) fn get_by_entry_index(
2221 &self,
2222 indexes: EntryIndexes,
2223 ) -> OccupiedEntryRef<'_, T> {
2224 match indexes {
2225 EntryIndexes::Unique(index) => OccupiedEntryRef::Unique(
2226 self.items.get(index).expect("index is valid"),
2227 ),
2228 EntryIndexes::NonUnique { index1, index2 } => {
2229 let by_key1 = index1
2230 .map(|k| self.items.get(k).expect("key1 index is valid"));
2231 let by_key2 = index2
2232 .map(|k| self.items.get(k).expect("key2 index is valid"));
2233 OccupiedEntryRef::NonUnique { by_key1, by_key2 }
2234 }
2235 }
2236 }
2237
2238 pub(super) fn get_by_entry_index_mut(
2239 &mut self,
2240 indexes: EntryIndexes,
2241 ) -> OccupiedEntryMut<'_, T, S> {
2242 match indexes.disjoint_keys() {
2243 DisjointKeys::Unique(index) => {
2244 let item = self.items.get_mut(index).expect("index is valid");
2245 let state = self.tables.state.clone();
2246 let hashes =
2247 self.tables.make_hashes::<T>(&item.key1(), &item.key2());
2248 OccupiedEntryMut::Unique(RefMut::new(state, hashes, item))
2249 }
2250 DisjointKeys::Key1(index1) => {
2251 let item =
2252 self.items.get_mut(index1).expect("key1 index is valid");
2253 let state = self.tables.state.clone();
2254 let hashes =
2255 self.tables.make_hashes::<T>(&item.key1(), &item.key2());
2256 OccupiedEntryMut::NonUnique {
2257 by_key1: Some(RefMut::new(state, hashes, item)),
2258 by_key2: None,
2259 }
2260 }
2261 DisjointKeys::Key2(index2) => {
2262 let item =
2263 self.items.get_mut(index2).expect("key2 index is valid");
2264 let state = self.tables.state.clone();
2265 let hashes =
2266 self.tables.make_hashes::<T>(&item.key1(), &item.key2());
2267 OccupiedEntryMut::NonUnique {
2268 by_key1: None,
2269 by_key2: Some(RefMut::new(state, hashes, item)),
2270 }
2271 }
2272 DisjointKeys::Key12(indexes) => {
2273 let state = self.tables.state.clone();
2274 let mut items = self.items.get_disjoint_mut(indexes);
2275 let item1 = items[0].take().expect("key1 index is valid");
2276 let item2 = items[1].take().expect("key2 index is valid");
2277 let hashes1 =
2278 self.tables.make_hashes::<T>(&item1.key1(), &item1.key2());
2279 let hashes2 =
2280 self.tables.make_hashes::<T>(&item2.key1(), &item2.key2());
2281
2282 OccupiedEntryMut::NonUnique {
2283 by_key1: Some(RefMut::new(state.clone(), hashes1, item1)),
2284 by_key2: Some(RefMut::new(state, hashes2, item2)),
2285 }
2286 }
2287 }
2288 }
2289
2290 pub(super) fn get_by_index_mut(
2291 &mut self,
2292 index: ItemIndex,
2293 ) -> Option<RefMut<'_, T, S>> {
2294 let borrowed = self.items.get_mut(index)?;
2295 let state = self.tables.state.clone();
2296 let hashes =
2297 self.tables.make_hashes::<T>(&borrowed.key1(), &borrowed.key2());
2298 let item = &mut self.items[index];
2299 Some(RefMut::new(state, hashes, item))
2300 }
2301
2302 pub(super) fn insert_unique_impl(
2303 &mut self,
2304 value: T,
2305 ) -> Result<ItemIndex, DuplicateItem<T, &T>> {
2306 let mut duplicates = BTreeSet::new();
2307
2308 // Check for duplicates *before* inserting the new item, because we
2309 // don't want to partially insert the new item and then have to roll
2310 // back.
2311 let state = &self.tables.state;
2312 let (e1, e2) = {
2313 let k1 = value.key1();
2314 let k2 = value.key2();
2315
2316 let e1 = detect_dup_or_insert(
2317 self.tables
2318 .k1_to_item
2319 .entry(state, k1, |index| self.items[index].key1()),
2320 &mut duplicates,
2321 );
2322 let e2 = detect_dup_or_insert(
2323 self.tables
2324 .k2_to_item
2325 .entry(state, k2, |index| self.items[index].key2()),
2326 &mut duplicates,
2327 );
2328 (e1, e2)
2329 };
2330
2331 if !duplicates.is_empty() {
2332 return Err(DuplicateItem::__internal_new(
2333 value,
2334 duplicates.iter().map(|ix| &self.items[*ix]).collect(),
2335 ));
2336 }
2337
2338 let next_index = self.items.assert_can_grow().insert(value);
2339 // e1 and e2 are all Some because if they were None, duplicates
2340 // would be non-empty, and we'd have bailed out earlier.
2341 e1.unwrap().insert(next_index);
2342 e2.unwrap().insert(next_index);
2343
2344 Ok(next_index)
2345 }
2346
2347 pub(super) fn remove_by_entry_index(
2348 &mut self,
2349 indexes: EntryIndexes,
2350 ) -> Vec<T> {
2351 let prepared = self.prepare_entry_index_removal(indexes);
2352 let mut old_items = Vec::with_capacity(prepared.len());
2353
2354 for duplicate in prepared {
2355 old_items.push(
2356 self.remove_duplicate(duplicate)
2357 .expect("prepared duplicate index was present"),
2358 );
2359 }
2360
2361 old_items
2362 }
2363
2364 pub(super) fn remove_by_index(
2365 &mut self,
2366 remove_index: ItemIndex,
2367 ) -> Option<T> {
2368 // For panic safety, compute both key hashes and look up both table
2369 // entries while `self.items` still holds the value, then remove from
2370 // both tables and items in sequence. These lookups deliberately match
2371 // by `ItemIndex` rather than by user `Eq`: at this point we already
2372 // know which item is being removed, and user `Eq` might be
2373 // pathological. hashbrown's `find_entry_by_hash` is panic-safe because
2374 // the table is not mutated until `OccupiedEntry::remove` is called, so
2375 // a panic while hashing leaves items and both tables unmodified.
2376 // (Unlike the IdOrdMap path, no separate two-phase commit is needed:
2377 // the BTreeMap analog has to guard against a user-`Ord` panic during
2378 // the tree walk, but the hash walk here never invokes user code.)
2379 //
2380 // If either hash lookup misses — which happens when a `mem::forget`
2381 // on a `RefMut` bypassed the drop-time hash check and one of the
2382 // item's keys now hashes to a different bucket than its entry sits
2383 // in — fall back to a linear scan by `ItemIndex` for that table.
2384 // The fallback never invokes user `Hash`, so cleanup remains
2385 // panic-safe.
2386 let item = self.items.get(remove_index)?;
2387 let state = &self.tables.state;
2388 let hash1 = state.hash_one(item.key1());
2389 let hash2 = state.hash_one(item.key2());
2390 match self
2391 .tables
2392 .k1_to_item
2393 .find_entry_by_hash(hash1, |index| index == remove_index)
2394 {
2395 Ok(entry) => entry.remove(),
2396 Err(()) => self.tables.k1_to_item.remove_by_index(remove_index),
2397 }
2398 match self
2399 .tables
2400 .k2_to_item
2401 .find_entry_by_hash(hash2, |index| index == remove_index)
2402 {
2403 Ok(entry) => entry.remove(),
2404 Err(()) => self.tables.k2_to_item.remove_by_index(remove_index),
2405 }
2406 Some(
2407 self.items
2408 .remove(remove_index)
2409 .expect("items[remove_index] was Occupied above"),
2410 )
2411 }
2412
2413 /// Removes the item at `duplicate`, using already-computed key hashes when
2414 /// possible.
2415 ///
2416 /// The caller must ensure:
2417 ///
2418 /// * all user-controlled key extraction and hashing for the item at
2419 /// `duplicate.index` has already completed;
2420 /// * the item at `duplicate.index` has not changed since those hashes were
2421 /// computed;
2422 /// * removing this index from the item store and key tables preserves the
2423 /// map/table invariants.
2424 ///
2425 /// The provided `duplicate.hashes` allow the normal commit path to remove
2426 /// key-table entries without recomputing user-controlled hashes. If a
2427 /// prehashed lookup misses, this falls back to removing by `ItemIndex`,
2428 /// which performs a linear scan over cached indexes and does not re-enter
2429 /// user code.
2430 fn remove_duplicate(&mut self, duplicate: PreparedDuplicate) -> Option<T> {
2431 let _ = self.items.get(duplicate.index)?;
2432
2433 let [hash1, hash2] = duplicate.hashes;
2434
2435 match self
2436 .tables
2437 .k1_to_item
2438 .find_entry_by_hash(hash1.hash(), |index| index == duplicate.index)
2439 {
2440 Ok(entry) => entry.remove(),
2441 Err(()) => self.tables.k1_to_item.remove_by_index(duplicate.index),
2442 }
2443
2444 match self
2445 .tables
2446 .k2_to_item
2447 .find_entry_by_hash(hash2.hash(), |index| index == duplicate.index)
2448 {
2449 Ok(entry) => entry.remove(),
2450 Err(()) => self.tables.k2_to_item.remove_by_index(duplicate.index),
2451 }
2452
2453 Some(
2454 self.items
2455 .remove(duplicate.index)
2456 .expect("items[duplicate.index] was Occupied above"),
2457 )
2458 }
2459
2460 pub(super) fn replace_at_indexes(
2461 &mut self,
2462 indexes: EntryIndexes,
2463 value: T,
2464 ) -> (ItemIndex, Vec<T>) {
2465 match indexes {
2466 EntryIndexes::Unique(index) => {
2467 {
2468 let old_item = &self.items[index];
2469 if old_item.key1() != value.key1() {
2470 panic!("key1 mismatch");
2471 }
2472 if old_item.key2() != value.key2() {
2473 panic!("key2 mismatch");
2474 }
2475 }
2476
2477 let mut old_items = Vec::with_capacity(1);
2478 let old_item = self.items.replace(index, value);
2479 old_items.push(old_item);
2480
2481 (index, old_items)
2482 }
2483 EntryIndexes::NonUnique { index1, index2 } => {
2484 let prepared = self.prepare_insert_overwrite(&value);
2485
2486 if prepared.index1 != index1 {
2487 panic!("key1 mismatch");
2488 }
2489 if prepared.index2 != index2 {
2490 panic!("key2 mismatch");
2491 }
2492
2493 let mut old_items =
2494 Vec::with_capacity(prepared.duplicate_count());
2495
2496 self.try_reserve_insert_overwrite_commit(
2497 prepared.needs_new_item_slot(),
2498 )
2499 .expect("reserved item slot");
2500
2501 let next_index = self.commit_insert_overwrite(
2502 value,
2503 prepared,
2504 &mut old_items,
2505 );
2506
2507 (next_index, old_items)
2508 }
2509 }
2510 }
2511}
2512
2513impl<'a, T, S, A> fmt::Debug for BiHashMap<T, S, A>
2514where
2515 T: BiHashItem + fmt::Debug,
2516 T::K1<'a>: fmt::Debug,
2517 T::K2<'a>: fmt::Debug,
2518 T: 'a,
2519 A: Allocator,
2520{
2521 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2522 let mut map = f.debug_map();
2523 for item in self.items.values() {
2524 let key: KeyMap<'_, T> =
2525 KeyMap { key1: item.key1(), key2: item.key2() };
2526
2527 // SAFETY:
2528 //
2529 // * Lifetime extension: for a type T and two lifetime params 'a and
2530 // 'b, T<'a> and T<'b> aren't guaranteed to have the same layout,
2531 // but (a) that is true today and (b) it would be shocking and
2532 // break half the Rust ecosystem if that were to change in the
2533 // future.
2534 // * We only use key within the scope of this block before immediately
2535 // dropping it. In particular, map.entry calls key.fmt() without
2536 // holding a reference to it.
2537 let key: KeyMap<'a, T> = unsafe {
2538 core::mem::transmute::<KeyMap<'_, T>, KeyMap<'a, T>>(key)
2539 };
2540
2541 map.entry(&key as &dyn fmt::Debug, item);
2542 }
2543 map.finish()
2544 }
2545}
2546
2547struct KeyMap<'a, T: BiHashItem + 'a> {
2548 key1: T::K1<'a>,
2549 key2: T::K2<'a>,
2550}
2551
2552impl<'a, T: BiHashItem + 'a> fmt::Debug for KeyMap<'a, T>
2553where
2554 T::K1<'a>: fmt::Debug,
2555 T::K2<'a>: fmt::Debug,
2556{
2557 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2558 // We don't want to show key1 and key2 as a tuple since it's
2559 // misleading (suggests maps of tuples). The best we can do
2560 // instead is to show "{k1: "abc", k2: "xyz"}"
2561 f.debug_map()
2562 .entry(&StrDisplayAsDebug("k1"), &self.key1)
2563 .entry(&StrDisplayAsDebug("k2"), &self.key2)
2564 .finish()
2565 }
2566}
2567
2568/// The `PartialEq` implementation for `BiHashMap` checks that both maps have
2569/// the same items, regardless of insertion order.
2570///
2571/// # Examples
2572///
2573/// ```
2574/// # #[cfg(feature = "default-hasher")] {
2575/// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
2576///
2577/// #[derive(Debug, PartialEq, Eq)]
2578/// struct Item {
2579/// id: u32,
2580/// name: String,
2581/// value: i32,
2582/// }
2583///
2584/// impl BiHashItem for Item {
2585/// type K1<'a> = u32;
2586/// type K2<'a> = &'a str;
2587///
2588/// fn key1(&self) -> Self::K1<'_> {
2589/// self.id
2590/// }
2591/// fn key2(&self) -> Self::K2<'_> {
2592/// &self.name
2593/// }
2594/// bi_upcast!();
2595/// }
2596///
2597/// let mut map1 = BiHashMap::new();
2598/// map1.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
2599/// .unwrap();
2600/// map1.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
2601/// .unwrap();
2602///
2603/// let mut map2 = BiHashMap::new();
2604/// map2.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
2605/// .unwrap();
2606/// map2.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
2607/// .unwrap();
2608///
2609/// // Maps are equal even if items were inserted in different order
2610/// assert_eq!(map1, map2);
2611///
2612/// map2.insert_unique(Item { id: 3, name: "baz".to_string(), value: 200 })
2613/// .unwrap();
2614/// assert_ne!(map1, map2);
2615/// # }
2616/// ```
2617impl<T: BiHashItem + PartialEq, S: Clone + BuildHasher, A: Allocator> PartialEq
2618 for BiHashMap<T, S, A>
2619{
2620 fn eq(&self, other: &Self) -> bool {
2621 // Implementing PartialEq for BiHashMap is tricky because BiHashMap is
2622 // not semantically like an IndexMap: two maps are equivalent even if
2623 // their items are in a different order. In other words, any permutation
2624 // of items is equivalent.
2625 //
2626 // We also can't sort the items because they're not necessarily Ord.
2627 //
2628 // So we write a custom equality check that checks that each key in one
2629 // map points to the same item as in the other map.
2630
2631 if self.items.len() != other.items.len() {
2632 return false;
2633 }
2634
2635 // Walk over all the items in the first map and check that they point to
2636 // the same item in the second map.
2637 for item in self.items.values() {
2638 let k1 = item.key1();
2639 let k2 = item.key2();
2640
2641 // Check that the indexes are the same in the other map.
2642 let Some(other_ix1) = other.find1_index(&k1) else {
2643 return false;
2644 };
2645 let Some(other_ix2) = other.find2_index(&k2) else {
2646 return false;
2647 };
2648
2649 if other_ix1 != other_ix2 {
2650 // All the keys were present but they didn't point to the same
2651 // item.
2652 return false;
2653 }
2654
2655 // Check that the other map's item is the same as this map's
2656 // item. (This is what we use the `PartialEq` bound on T for.)
2657 //
2658 // Because we've checked that other_ix1 and other_ix2 are
2659 // Some, we know that it is valid and points to the expected item.
2660 let other_item = &other.items[other_ix1];
2661 if item != other_item {
2662 return false;
2663 }
2664 }
2665
2666 true
2667 }
2668}
2669
2670// The Eq bound on T ensures that the BiHashMap forms an equivalence class.
2671impl<T: BiHashItem + Eq, S: Clone + BuildHasher, A: Allocator> Eq
2672 for BiHashMap<T, S, A>
2673{
2674}
2675
2676fn detect_dup_or_insert<'a, A: Allocator>(
2677 item: hash_table::Entry<'a, A>,
2678 duplicates: &mut BTreeSet<ItemIndex>,
2679) -> Option<hash_table::VacantEntry<'a, A>> {
2680 match item {
2681 hash_table::Entry::Vacant(slot) => Some(slot),
2682 hash_table::Entry::Occupied(slot) => {
2683 duplicates.insert(slot.get());
2684 None
2685 }
2686 }
2687}
2688
2689/// The `Extend` implementation overwrites duplicates. In the future, there will
2690/// also be an `extend_unique` method that will return an error.
2691///
2692/// # Examples
2693///
2694/// ```
2695/// # #[cfg(feature = "default-hasher")] {
2696/// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
2697///
2698/// #[derive(Debug, PartialEq, Eq)]
2699/// struct Item {
2700/// id: u32,
2701/// name: String,
2702/// value: i32,
2703/// }
2704///
2705/// impl BiHashItem for Item {
2706/// type K1<'a> = u32;
2707/// type K2<'a> = &'a str;
2708///
2709/// fn key1(&self) -> Self::K1<'_> {
2710/// self.id
2711/// }
2712/// fn key2(&self) -> Self::K2<'_> {
2713/// &self.name
2714/// }
2715/// bi_upcast!();
2716/// }
2717///
2718/// let mut map = BiHashMap::new();
2719/// map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 }).unwrap();
2720///
2721/// let new_items = vec![
2722/// Item { id: 2, name: "bar".to_string(), value: 99 },
2723/// Item { id: 1, name: "baz".to_string(), value: 100 }, // overwrites existing
2724/// ];
2725///
2726/// map.extend(new_items);
2727/// assert_eq!(map.len(), 2);
2728/// assert_eq!(map.get1(&1).unwrap().name, "baz"); // overwritten
2729/// assert_eq!(map.get1(&1).unwrap().value, 100);
2730/// # }
2731/// ```
2732impl<T: BiHashItem, S: Clone + BuildHasher, A: Allocator> Extend<T>
2733 for BiHashMap<T, S, A>
2734{
2735 fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
2736 // Keys may already be present in the map, or multiple times in the
2737 // iterator. Reserve the entire hint lower bound if the map is empty.
2738 // Otherwise reserve half the hint (rounded up), so the map will only
2739 // resize twice in the worst case.
2740 let iter = iter.into_iter();
2741 let reserve = if self.is_empty() {
2742 iter.size_hint().0
2743 } else {
2744 iter.size_hint().0.div_ceil(2)
2745 };
2746 self.reserve(reserve);
2747 for item in iter {
2748 self.insert_overwrite(item);
2749 }
2750 }
2751}
2752
2753impl<'a, T: BiHashItem, S: Clone + BuildHasher, A: Allocator> IntoIterator
2754 for &'a BiHashMap<T, S, A>
2755{
2756 type Item = &'a T;
2757 type IntoIter = Iter<'a, T>;
2758
2759 #[inline]
2760 fn into_iter(self) -> Self::IntoIter {
2761 self.iter()
2762 }
2763}
2764
2765impl<'a, T: BiHashItem, S: Clone + BuildHasher, A: Allocator> IntoIterator
2766 for &'a mut BiHashMap<T, S, A>
2767{
2768 type Item = RefMut<'a, T, S>;
2769 type IntoIter = IterMut<'a, T, S, A>;
2770
2771 #[inline]
2772 fn into_iter(self) -> Self::IntoIter {
2773 self.iter_mut()
2774 }
2775}
2776
2777impl<T: BiHashItem, S: Clone + BuildHasher, A: Allocator> IntoIterator
2778 for BiHashMap<T, S, A>
2779{
2780 type Item = T;
2781 type IntoIter = IntoIter<T, A>;
2782
2783 #[inline]
2784 fn into_iter(self) -> Self::IntoIter {
2785 IntoIter::new(self.items)
2786 }
2787}
2788
2789/// The `FromIterator` implementation for `BiHashMap` overwrites duplicate
2790/// items.
2791///
2792/// # Examples
2793///
2794/// ```
2795/// # #[cfg(feature = "default-hasher")] {
2796/// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
2797///
2798/// #[derive(Debug, PartialEq, Eq)]
2799/// struct Item {
2800/// id: u32,
2801/// name: String,
2802/// value: i32,
2803/// }
2804///
2805/// impl BiHashItem for Item {
2806/// type K1<'a> = u32;
2807/// type K2<'a> = &'a str;
2808///
2809/// fn key1(&self) -> Self::K1<'_> {
2810/// self.id
2811/// }
2812/// fn key2(&self) -> Self::K2<'_> {
2813/// &self.name
2814/// }
2815/// bi_upcast!();
2816/// }
2817///
2818/// let items = vec![
2819/// Item { id: 1, name: "foo".to_string(), value: 42 },
2820/// Item { id: 2, name: "bar".to_string(), value: 99 },
2821/// Item { id: 1, name: "baz".to_string(), value: 100 }, // overwrites first item
2822/// ];
2823///
2824/// let map: BiHashMap<Item> = items.into_iter().collect();
2825/// assert_eq!(map.len(), 2);
2826/// assert_eq!(map.get1(&1).unwrap().name, "baz"); // overwritten
2827/// assert_eq!(map.get1(&1).unwrap().value, 100);
2828/// assert_eq!(map.get1(&2).unwrap().value, 99);
2829/// # }
2830/// ```
2831impl<T: BiHashItem, S: Clone + BuildHasher + Default, A: Default + Allocator>
2832 FromIterator<T> for BiHashMap<T, S, A>
2833{
2834 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
2835 let mut map = BiHashMap::default();
2836 map.extend(iter);
2837 map
2838 }
2839}