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