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