iddqd/id_hash_map/imp.rs
1use super::{
2 Entry, IdHashItem, IntoIter, Iter, IterMut, OccupiedEntry, RefMut,
3 VacantEntry, tables::IdHashMapTables,
4};
5use crate::{
6 DefaultHashBuilder,
7 errors::DuplicateItem,
8 internal::{ValidateCompact, ValidationError},
9 support::{
10 alloc::{Allocator, Global, global_alloc},
11 borrow::DormantMutRef,
12 item_set::ItemSet,
13 map_hash::MapHash,
14 },
15};
16use alloc::collections::BTreeSet;
17use core::{
18 fmt,
19 hash::{BuildHasher, Hash},
20};
21use equivalent::Equivalent;
22use hashbrown::hash_table;
23
24/// A hash map where the key is part of the value.
25///
26/// The storage mechanism is a fast hash table of integer indexes to items, with
27/// these indexes stored in a hash table. This allows for efficient lookups by
28/// the key and prevents duplicates.
29///
30/// # Examples
31///
32/// ```
33/// # #[cfg(feature = "default-hasher")] {
34/// use iddqd::{IdHashItem, IdHashMap, id_upcast};
35///
36/// // Define a struct with a key.
37/// #[derive(Debug, PartialEq, Eq, Hash)]
38/// struct MyItem {
39/// id: String,
40/// value: u32,
41/// }
42///
43/// // Implement IdHashItem for the struct.
44/// impl IdHashItem for MyItem {
45/// // Keys can borrow from the item.
46/// type Key<'a> = &'a str;
47///
48/// fn key(&self) -> Self::Key<'_> {
49/// &self.id
50/// }
51///
52/// id_upcast!();
53/// }
54///
55/// // Create an IdHashMap and insert items.
56/// let mut map = IdHashMap::new();
57/// map.insert_unique(MyItem { id: "foo".to_string(), value: 42 }).unwrap();
58/// map.insert_unique(MyItem { id: "bar".to_string(), value: 20 }).unwrap();
59///
60/// // Look up items by their keys.
61/// assert_eq!(map.get("foo").unwrap().value, 42);
62/// assert_eq!(map.get("bar").unwrap().value, 20);
63/// assert!(map.get("baz").is_none());
64/// # }
65/// ```
66#[derive(Clone)]
67pub struct IdHashMap<T, S = DefaultHashBuilder, A: Allocator = Global> {
68 pub(super) items: ItemSet<T, A>,
69 pub(super) tables: IdHashMapTables<S, A>,
70}
71
72impl<T: IdHashItem, S: Default, A: Allocator + Default> Default
73 for IdHashMap<T, S, A>
74{
75 fn default() -> Self {
76 Self {
77 items: ItemSet::with_capacity_in(0, A::default()),
78 tables: IdHashMapTables::default(),
79 }
80 }
81}
82
83#[cfg(feature = "default-hasher")]
84impl<T: IdHashItem> IdHashMap<T> {
85 /// Creates a new, empty `IdHashMap`.
86 ///
87 /// # Examples
88 ///
89 /// ```
90 /// # #[cfg(feature = "default-hasher")] {
91 /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
92 ///
93 /// #[derive(Debug, PartialEq, Eq, Hash)]
94 /// struct Item {
95 /// id: String,
96 /// value: u32,
97 /// }
98 ///
99 /// impl IdHashItem for Item {
100 /// type Key<'a> = &'a str;
101 /// fn key(&self) -> Self::Key<'_> {
102 /// &self.id
103 /// }
104 /// id_upcast!();
105 /// }
106 ///
107 /// let map: IdHashMap<Item> = IdHashMap::new();
108 /// assert!(map.is_empty());
109 /// assert_eq!(map.len(), 0);
110 /// # }
111 /// ```
112 #[inline]
113 pub fn new() -> Self {
114 Self { items: ItemSet::new(), tables: IdHashMapTables::default() }
115 }
116
117 /// Creates a new `IdHashMap` with the given capacity.
118 ///
119 /// # Examples
120 ///
121 /// ```
122 /// # #[cfg(feature = "default-hasher")] {
123 /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
124 ///
125 /// #[derive(Debug, PartialEq, Eq, Hash)]
126 /// struct Item {
127 /// id: String,
128 /// value: u32,
129 /// }
130 ///
131 /// impl IdHashItem for Item {
132 /// type Key<'a> = &'a str;
133 /// fn key(&self) -> Self::Key<'_> {
134 /// &self.id
135 /// }
136 /// id_upcast!();
137 /// }
138 ///
139 /// let map: IdHashMap<Item> = IdHashMap::with_capacity(10);
140 /// assert!(map.capacity() >= 10);
141 /// assert!(map.is_empty());
142 /// # }
143 /// ```
144 pub fn with_capacity(capacity: usize) -> Self {
145 Self {
146 items: ItemSet::with_capacity_in(capacity, global_alloc()),
147 tables: IdHashMapTables::with_capacity_and_hasher_in(
148 capacity,
149 DefaultHashBuilder::default(),
150 global_alloc(),
151 ),
152 }
153 }
154}
155
156impl<T: IdHashItem, S: BuildHasher> IdHashMap<T, S> {
157 /// Creates a new, empty `IdHashMap` with the given hasher.
158 ///
159 /// # Examples
160 ///
161 /// ```
162 /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
163 /// use std::collections::hash_map::RandomState;
164 ///
165 /// #[derive(Debug, PartialEq, Eq, Hash)]
166 /// struct Item {
167 /// id: String,
168 /// value: u32,
169 /// }
170 ///
171 /// impl IdHashItem for Item {
172 /// type Key<'a> = &'a str;
173 /// fn key(&self) -> Self::Key<'_> {
174 /// &self.id
175 /// }
176 /// id_upcast!();
177 /// }
178 ///
179 /// let hasher = RandomState::new();
180 /// let map: IdHashMap<Item, _> = IdHashMap::with_hasher(hasher);
181 /// assert!(map.is_empty());
182 /// ```
183 pub const fn with_hasher(hasher: S) -> Self {
184 Self {
185 items: ItemSet::new(),
186 tables: IdHashMapTables::with_hasher_in(hasher, global_alloc()),
187 }
188 }
189
190 /// Creates a new `IdHashMap` with the given capacity and hasher.
191 ///
192 /// # Examples
193 ///
194 /// ```
195 /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
196 /// use std::collections::hash_map::RandomState;
197 ///
198 /// #[derive(Debug, PartialEq, Eq, Hash)]
199 /// struct Item {
200 /// id: String,
201 /// value: u32,
202 /// }
203 ///
204 /// impl IdHashItem for Item {
205 /// type Key<'a> = &'a str;
206 /// fn key(&self) -> Self::Key<'_> {
207 /// &self.id
208 /// }
209 /// id_upcast!();
210 /// }
211 ///
212 /// let hasher = RandomState::new();
213 /// let map: IdHashMap<Item, _> =
214 /// IdHashMap::with_capacity_and_hasher(10, hasher);
215 /// assert!(map.capacity() >= 10);
216 /// assert!(map.is_empty());
217 /// ```
218 pub fn with_capacity_and_hasher(capacity: usize, hasher: S) -> Self {
219 Self {
220 items: ItemSet::with_capacity_in(capacity, global_alloc()),
221 tables: IdHashMapTables::with_capacity_and_hasher_in(
222 capacity,
223 hasher,
224 global_alloc(),
225 ),
226 }
227 }
228}
229
230#[cfg(feature = "default-hasher")]
231impl<T: IdHashItem, A: Clone + Allocator> IdHashMap<T, DefaultHashBuilder, A> {
232 /// Creates a new empty `IdHashMap` using the given allocator.
233 ///
234 /// Requires the `allocator-api2` feature to be enabled.
235 ///
236 /// # Examples
237 ///
238 /// Using the [`bumpalo`](https://docs.rs/bumpalo) allocator:
239 ///
240 /// ```
241 /// # #[cfg(all(feature = "default-hasher", feature = "allocator-api2"))] {
242 /// use iddqd::{IdHashMap, IdHashItem, id_upcast};
243 /// # use iddqd_test_utils::bumpalo;
244 ///
245 /// #[derive(Debug, PartialEq, Eq, Hash)]
246 /// struct Item {
247 /// id: String,
248 /// value: u32,
249 /// }
250 ///
251 /// impl IdHashItem for Item {
252 /// type Key<'a> = &'a str;
253 /// fn key(&self) -> Self::Key<'_> { &self.id }
254 /// id_upcast!();
255 /// }
256 ///
257 /// // Define a new allocator.
258 /// let bump = bumpalo::Bump::new();
259 /// // Create a new IdHashMap using the allocator.
260 /// let map: IdHashMap<Item, _, &bumpalo::Bump> = IdHashMap::new_in(&bump);
261 /// assert!(map.is_empty());
262 /// # }
263 /// ```
264 pub fn new_in(alloc: A) -> Self {
265 Self {
266 items: ItemSet::with_capacity_in(0, alloc.clone()),
267 tables: IdHashMapTables::with_capacity_and_hasher_in(
268 0,
269 DefaultHashBuilder::default(),
270 alloc,
271 ),
272 }
273 }
274
275 /// Creates an empty `IdHashMap` with the specified capacity using the given
276 /// allocator.
277 ///
278 /// Requires the `allocator-api2` feature to be enabled.
279 ///
280 /// # Examples
281 ///
282 /// Using the [`bumpalo`](https://docs.rs/bumpalo) allocator:
283 ///
284 /// ```
285 /// # #[cfg(all(feature = "default-hasher", feature = "allocator-api2"))] {
286 /// use iddqd::{IdHashMap, IdHashItem, id_upcast};
287 /// # use iddqd_test_utils::bumpalo;
288 ///
289 /// #[derive(Debug, PartialEq, Eq, Hash)]
290 /// struct Item {
291 /// id: String,
292 /// value: u32,
293 /// }
294 ///
295 /// impl IdHashItem for Item {
296 /// type Key<'a> = &'a str;
297 /// fn key(&self) -> Self::Key<'_> { &self.id }
298 /// id_upcast!();
299 /// }
300 ///
301 /// // Define a new allocator.
302 /// let bump = bumpalo::Bump::new();
303 /// // Create a new IdHashMap with capacity using the allocator.
304 /// let map: IdHashMap<Item, _, &bumpalo::Bump> = IdHashMap::with_capacity_in(10, &bump);
305 /// assert!(map.capacity() >= 10);
306 /// assert!(map.is_empty());
307 /// # }
308 /// ```
309 pub fn with_capacity_in(capacity: usize, alloc: A) -> Self {
310 Self {
311 items: ItemSet::with_capacity_in(capacity, alloc.clone()),
312 tables: IdHashMapTables::with_capacity_and_hasher_in(
313 capacity,
314 DefaultHashBuilder::default(),
315 alloc,
316 ),
317 }
318 }
319}
320
321impl<T: IdHashItem, S: BuildHasher, A: Clone + Allocator> IdHashMap<T, S, A> {
322 /// Creates a new, empty `IdHashMap` with the given hasher and allocator.
323 ///
324 /// Requires the `allocator-api2` feature to be enabled.
325 ///
326 /// # Examples
327 ///
328 /// Using the [`bumpalo`](https://docs.rs/bumpalo) allocator:
329 ///
330 /// ```
331 /// # #[cfg(feature = "allocator-api2")] {
332 /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
333 /// use std::collections::hash_map::RandomState;
334 /// # use iddqd_test_utils::bumpalo;
335 ///
336 /// #[derive(Debug, PartialEq, Eq, Hash)]
337 /// struct Item {
338 /// id: String,
339 /// value: u32,
340 /// }
341 ///
342 /// impl IdHashItem for Item {
343 /// type Key<'a> = &'a str;
344 /// fn key(&self) -> Self::Key<'_> {
345 /// &self.id
346 /// }
347 /// id_upcast!();
348 /// }
349 ///
350 /// // Define a new allocator.
351 /// let bump = bumpalo::Bump::new();
352 /// let hasher = RandomState::new();
353 /// // Create a new IdHashMap with hasher using the allocator.
354 /// let map: IdHashMap<Item, _, &bumpalo::Bump> =
355 /// IdHashMap::with_hasher_in(hasher, &bump);
356 /// assert!(map.is_empty());
357 /// # }
358 /// ```
359 pub fn with_hasher_in(hasher: S, alloc: A) -> Self {
360 Self {
361 items: ItemSet::new_in(alloc.clone()),
362 tables: IdHashMapTables::with_hasher_in(hasher, alloc),
363 }
364 }
365
366 /// Creates a new, empty `IdHashMap` with the given capacity, hasher, and
367 /// allocator.
368 ///
369 /// Requires the `allocator-api2` feature to be enabled.
370 ///
371 /// # Examples
372 ///
373 /// Using the [`bumpalo`](https://docs.rs/bumpalo) allocator:
374 ///
375 /// ```
376 /// # #[cfg(feature = "allocator-api2")] {
377 /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
378 /// use std::collections::hash_map::RandomState;
379 /// # use iddqd_test_utils::bumpalo;
380 ///
381 /// #[derive(Debug, PartialEq, Eq, Hash)]
382 /// struct Item {
383 /// id: String,
384 /// value: u32,
385 /// }
386 ///
387 /// impl IdHashItem for Item {
388 /// type Key<'a> = &'a str;
389 /// fn key(&self) -> Self::Key<'_> {
390 /// &self.id
391 /// }
392 /// id_upcast!();
393 /// }
394 ///
395 /// // Define a new allocator.
396 /// let bump = bumpalo::Bump::new();
397 /// let hasher = RandomState::new();
398 /// // Create a new IdHashMap with capacity and hasher using the allocator.
399 /// let map: IdHashMap<Item, _, &bumpalo::Bump> =
400 /// IdHashMap::with_capacity_and_hasher_in(10, hasher, &bump);
401 /// assert!(map.capacity() >= 10);
402 /// assert!(map.is_empty());
403 /// # }
404 /// ```
405 pub fn with_capacity_and_hasher_in(
406 capacity: usize,
407 hasher: S,
408 alloc: A,
409 ) -> Self {
410 Self {
411 items: ItemSet::with_capacity_in(capacity, alloc.clone()),
412 tables: IdHashMapTables::with_capacity_and_hasher_in(
413 capacity, hasher, alloc,
414 ),
415 }
416 }
417}
418
419impl<T: IdHashItem, S: Clone + BuildHasher, A: Allocator> IdHashMap<T, S, A> {
420 #[cfg(feature = "daft")]
421 pub(crate) fn hasher(&self) -> &S {
422 self.tables.hasher()
423 }
424
425 /// Returns the allocator.
426 ///
427 /// Requires the `allocator-api2` feature to be enabled.
428 ///
429 /// # Examples
430 ///
431 /// Using the [`bumpalo`](https://docs.rs/bumpalo) allocator:
432 ///
433 /// ```
434 /// # #[cfg(all(feature = "default-hasher", feature = "allocator-api2"))] {
435 /// use iddqd::{IdHashMap, IdHashItem, id_upcast};
436 /// # use iddqd_test_utils::bumpalo;
437 ///
438 /// #[derive(Debug, PartialEq, Eq, Hash)]
439 /// struct Item {
440 /// id: String,
441 /// value: u32,
442 /// }
443 ///
444 /// impl IdHashItem for Item {
445 /// type Key<'a> = &'a str;
446 /// fn key(&self) -> Self::Key<'_> { &self.id }
447 /// id_upcast!();
448 /// }
449 ///
450 /// // Define a new allocator.
451 /// let bump = bumpalo::Bump::new();
452 /// // Create a new IdHashMap using the allocator.
453 /// let map: IdHashMap<Item, _, &bumpalo::Bump> = IdHashMap::new_in(&bump);
454 /// let _allocator = map.allocator();
455 /// # }
456 /// ```
457 pub fn allocator(&self) -> &A {
458 self.items.allocator()
459 }
460
461 /// Returns the currently allocated capacity of the map.
462 ///
463 /// # Examples
464 ///
465 /// ```
466 /// # #[cfg(feature = "default-hasher")] {
467 /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
468 ///
469 /// #[derive(Debug, PartialEq, Eq, Hash)]
470 /// struct Item {
471 /// id: String,
472 /// value: u32,
473 /// }
474 ///
475 /// impl IdHashItem for Item {
476 /// type Key<'a> = &'a str;
477 /// fn key(&self) -> Self::Key<'_> {
478 /// &self.id
479 /// }
480 /// id_upcast!();
481 /// }
482 ///
483 /// let map: IdHashMap<Item> = IdHashMap::with_capacity(10);
484 /// assert!(map.capacity() >= 10);
485 /// # }
486 /// ```
487 pub fn capacity(&self) -> usize {
488 // items and tables.capacity might theoretically diverge: use
489 // items.capacity.
490 self.items.capacity()
491 }
492
493 /// Returns true if the map is empty.
494 ///
495 /// # Examples
496 ///
497 /// ```
498 /// # #[cfg(feature = "default-hasher")] {
499 /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
500 ///
501 /// #[derive(Debug, PartialEq, Eq, Hash)]
502 /// struct Item {
503 /// id: String,
504 /// value: u32,
505 /// }
506 ///
507 /// impl IdHashItem for Item {
508 /// type Key<'a> = &'a str;
509 /// fn key(&self) -> Self::Key<'_> {
510 /// &self.id
511 /// }
512 /// id_upcast!();
513 /// }
514 ///
515 /// let mut map = IdHashMap::new();
516 /// assert!(map.is_empty());
517 ///
518 /// map.insert_unique(Item { id: "foo".to_string(), value: 42 }).unwrap();
519 /// assert!(!map.is_empty());
520 /// # }
521 /// ```
522 #[inline]
523 pub fn is_empty(&self) -> bool {
524 self.items.is_empty()
525 }
526
527 /// Returns the number of items in the map.
528 ///
529 /// # Examples
530 ///
531 /// ```
532 /// # #[cfg(feature = "default-hasher")] {
533 /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
534 ///
535 /// #[derive(Debug, PartialEq, Eq, Hash)]
536 /// struct Item {
537 /// id: String,
538 /// value: u32,
539 /// }
540 ///
541 /// impl IdHashItem for Item {
542 /// type Key<'a> = &'a str;
543 /// fn key(&self) -> Self::Key<'_> {
544 /// &self.id
545 /// }
546 /// id_upcast!();
547 /// }
548 ///
549 /// let mut map = IdHashMap::new();
550 /// assert_eq!(map.len(), 0);
551 ///
552 /// map.insert_unique(Item { id: "foo".to_string(), value: 42 }).unwrap();
553 /// assert_eq!(map.len(), 1);
554 ///
555 /// map.insert_unique(Item { id: "bar".to_string(), value: 20 }).unwrap();
556 /// assert_eq!(map.len(), 2);
557 /// # }
558 /// ```
559 #[inline]
560 pub fn len(&self) -> usize {
561 self.items.len()
562 }
563
564 /// Clears the map, removing all items.
565 ///
566 /// # Examples
567 ///
568 /// ```
569 /// # #[cfg(feature = "default-hasher")] {
570 /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
571 ///
572 /// #[derive(Debug, PartialEq, Eq, Hash)]
573 /// struct Item {
574 /// id: String,
575 /// value: u32,
576 /// }
577 ///
578 /// impl IdHashItem for Item {
579 /// type Key<'a> = &'a str;
580 /// fn key(&self) -> Self::Key<'_> {
581 /// &self.id
582 /// }
583 /// id_upcast!();
584 /// }
585 ///
586 /// let mut map = IdHashMap::new();
587 /// map.insert_unique(Item { id: "foo".to_string(), value: 42 }).unwrap();
588 /// map.insert_unique(Item { id: "bar".to_string(), value: 20 }).unwrap();
589 /// assert_eq!(map.len(), 2);
590 ///
591 /// map.clear();
592 /// assert!(map.is_empty());
593 /// assert_eq!(map.len(), 0);
594 /// # }
595 /// ```
596 pub fn clear(&mut self) {
597 self.items.clear();
598 self.tables.key_to_item.clear();
599 }
600
601 /// Iterates over the items in the map.
602 ///
603 /// Similar to [`HashMap`], the iteration order is arbitrary and not
604 /// guaranteed to be stable.
605 ///
606 /// # Examples
607 ///
608 /// ```
609 /// # #[cfg(feature = "default-hasher")] {
610 /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
611 ///
612 /// #[derive(Debug, PartialEq, Eq, Hash)]
613 /// struct Item {
614 /// id: String,
615 /// value: u32,
616 /// }
617 ///
618 /// impl IdHashItem for Item {
619 /// type Key<'a> = &'a str;
620 /// fn key(&self) -> Self::Key<'_> {
621 /// &self.id
622 /// }
623 /// id_upcast!();
624 /// }
625 ///
626 /// let mut map = IdHashMap::new();
627 /// map.insert_unique(Item { id: "foo".to_string(), value: 42 }).unwrap();
628 /// map.insert_unique(Item { id: "bar".to_string(), value: 20 }).unwrap();
629 ///
630 /// let mut values: Vec<u32> = map.iter().map(|item| item.value).collect();
631 /// values.sort();
632 /// assert_eq!(values, vec![20, 42]);
633 /// # }
634 /// ```
635 ///
636 /// [`HashMap`]: std::collections::HashMap
637 #[inline]
638 pub fn iter(&self) -> Iter<'_, T> {
639 Iter::new(&self.items)
640 }
641
642 /// Iterates over the items in the map, allowing for mutation.
643 ///
644 /// Similar to [`HashMap`], the iteration order is arbitrary and not
645 /// guaranteed to be stable.
646 ///
647 /// # Examples
648 ///
649 /// ```
650 /// # #[cfg(feature = "default-hasher")] {
651 /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
652 ///
653 /// #[derive(Debug, PartialEq, Eq, Hash)]
654 /// struct Item {
655 /// id: String,
656 /// value: u32,
657 /// }
658 ///
659 /// impl IdHashItem for Item {
660 /// type Key<'a> = &'a str;
661 /// fn key(&self) -> Self::Key<'_> {
662 /// &self.id
663 /// }
664 /// id_upcast!();
665 /// }
666 ///
667 /// let mut map = IdHashMap::new();
668 /// map.insert_unique(Item { id: "foo".to_string(), value: 42 }).unwrap();
669 /// map.insert_unique(Item { id: "bar".to_string(), value: 20 }).unwrap();
670 ///
671 /// for mut item in map.iter_mut() {
672 /// item.value *= 2;
673 /// }
674 ///
675 /// assert_eq!(map.get("foo").unwrap().value, 84);
676 /// assert_eq!(map.get("bar").unwrap().value, 40);
677 /// # }
678 /// ```
679 ///
680 /// [`HashMap`]: std::collections::HashMap
681 #[inline]
682 pub fn iter_mut(&mut self) -> IterMut<'_, T, S, A> {
683 IterMut::new(&self.tables, &mut self.items)
684 }
685
686 /// Checks general invariants of the map.
687 ///
688 /// The code below always upholds these invariants, but it's useful to have
689 /// an explicit check for tests.
690 #[doc(hidden)]
691 pub fn validate(
692 &self,
693 compactness: ValidateCompact,
694 ) -> Result<(), ValidationError>
695 where
696 T: fmt::Debug,
697 {
698 self.items.validate(compactness)?;
699 self.tables.validate(self.len(), compactness)?;
700
701 // Check that the indexes are all correct.
702 for (&ix, item) in self.items.iter() {
703 let key = item.key();
704 let Some(ix1) = self.find_index(&key) else {
705 return Err(ValidationError::general(format!(
706 "item at index {ix} has no key1 index"
707 )));
708 };
709
710 if ix1 != ix {
711 return Err(ValidationError::General(format!(
712 "item at index {ix} has mismatched indexes: ix1: {ix1}",
713 )));
714 }
715 }
716
717 Ok(())
718 }
719
720 /// Inserts a value into the map, removing and returning the conflicting
721 /// item, if any.
722 ///
723 /// # Examples
724 ///
725 /// ```
726 /// # #[cfg(feature = "default-hasher")] {
727 /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
728 ///
729 /// #[derive(Debug, PartialEq, Eq, Hash)]
730 /// struct Item {
731 /// id: String,
732 /// value: u32,
733 /// }
734 ///
735 /// impl IdHashItem for Item {
736 /// type Key<'a> = &'a str;
737 /// fn key(&self) -> Self::Key<'_> {
738 /// &self.id
739 /// }
740 /// id_upcast!();
741 /// }
742 ///
743 /// let mut map = IdHashMap::new();
744 ///
745 /// // First insertion returns None
746 /// let old = map.insert_overwrite(Item { id: "foo".to_string(), value: 42 });
747 /// assert!(old.is_none());
748 ///
749 /// // Second insertion with same key returns the old value
750 /// let old = map.insert_overwrite(Item { id: "foo".to_string(), value: 100 });
751 /// assert_eq!(old.unwrap().value, 42);
752 /// assert_eq!(map.get("foo").unwrap().value, 100);
753 /// # }
754 /// ```
755 #[doc(alias = "insert")]
756 pub fn insert_overwrite(&mut self, value: T) -> Option<T> {
757 // Trying to write this function for maximal efficiency can get very
758 // tricky, requiring delicate handling of indexes. We follow a very
759 // simple approach instead:
760 //
761 // 1. Remove items corresponding to the key that is already in the map.
762 // 2. Add the item to the map.
763
764 let duplicate = self.remove(&value.key());
765
766 if self.insert_unique(value).is_err() {
767 // We should never get here, because we just removed all the
768 // duplicates.
769 panic!("insert_unique failed after removing duplicates");
770 }
771
772 duplicate
773 }
774
775 /// Inserts a value into the set, returning an error if any duplicates were
776 /// added.
777 ///
778 /// # Examples
779 ///
780 /// ```
781 /// # #[cfg(feature = "default-hasher")] {
782 /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
783 ///
784 /// #[derive(Debug, PartialEq, Eq, Hash)]
785 /// struct Item {
786 /// id: String,
787 /// value: u32,
788 /// }
789 ///
790 /// impl IdHashItem for Item {
791 /// type Key<'a> = &'a str;
792 /// fn key(&self) -> Self::Key<'_> {
793 /// &self.id
794 /// }
795 /// id_upcast!();
796 /// }
797 ///
798 /// let mut map = IdHashMap::new();
799 ///
800 /// // First insertion succeeds
801 /// assert!(
802 /// map.insert_unique(Item { id: "foo".to_string(), value: 42 }).is_ok()
803 /// );
804 ///
805 /// // Second insertion with different key succeeds
806 /// assert!(
807 /// map.insert_unique(Item { id: "bar".to_string(), value: 20 }).is_ok()
808 /// );
809 ///
810 /// // Third insertion with duplicate key fails
811 /// assert!(
812 /// map.insert_unique(Item { id: "foo".to_string(), value: 100 }).is_err()
813 /// );
814 /// # }
815 /// ```
816 pub fn insert_unique(
817 &mut self,
818 value: T,
819 ) -> Result<(), DuplicateItem<T, &T>> {
820 let _ = self.insert_unique_impl(value)?;
821 Ok(())
822 }
823
824 /// Returns true if the map contains the given key.
825 ///
826 /// # Examples
827 ///
828 /// ```
829 /// # #[cfg(feature = "default-hasher")] {
830 /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
831 ///
832 /// #[derive(Debug, PartialEq, Eq, Hash)]
833 /// struct Item {
834 /// id: String,
835 /// value: u32,
836 /// }
837 ///
838 /// impl IdHashItem for Item {
839 /// type Key<'a> = &'a str;
840 /// fn key(&self) -> Self::Key<'_> {
841 /// &self.id
842 /// }
843 /// id_upcast!();
844 /// }
845 ///
846 /// let mut map = IdHashMap::new();
847 /// map.insert_unique(Item { id: "foo".to_string(), value: 42 }).unwrap();
848 ///
849 /// assert!(map.contains_key("foo"));
850 /// assert!(!map.contains_key("bar"));
851 /// # }
852 /// ```
853 pub fn contains_key<'a, Q>(&'a self, key1: &Q) -> bool
854 where
855 Q: ?Sized + Hash + Equivalent<T::Key<'a>>,
856 {
857 self.find_index(key1).is_some()
858 }
859
860 /// Gets a reference to the value associated with the given key.
861 ///
862 /// # Examples
863 ///
864 /// ```
865 /// # #[cfg(feature = "default-hasher")] {
866 /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
867 ///
868 /// #[derive(Debug, PartialEq, Eq, Hash)]
869 /// struct Item {
870 /// id: String,
871 /// value: u32,
872 /// }
873 ///
874 /// impl IdHashItem for Item {
875 /// type Key<'a> = &'a str;
876 /// fn key(&self) -> Self::Key<'_> {
877 /// &self.id
878 /// }
879 /// id_upcast!();
880 /// }
881 ///
882 /// let mut map = IdHashMap::new();
883 /// map.insert_unique(Item { id: "foo".to_string(), value: 42 }).unwrap();
884 ///
885 /// assert_eq!(map.get("foo").unwrap().value, 42);
886 /// assert!(map.get("bar").is_none());
887 /// # }
888 /// ```
889 pub fn get<'a, Q>(&'a self, key: &Q) -> Option<&'a T>
890 where
891 Q: ?Sized + Hash + Equivalent<T::Key<'a>>,
892 {
893 self.find_index(key).map(|ix| &self.items[ix])
894 }
895
896 /// Gets a mutable reference to the value associated with the given key.
897 ///
898 /// # Examples
899 ///
900 /// ```
901 /// # #[cfg(feature = "default-hasher")] {
902 /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
903 ///
904 /// #[derive(Debug, PartialEq, Eq, Hash)]
905 /// struct Item {
906 /// id: String,
907 /// value: u32,
908 /// }
909 ///
910 /// impl IdHashItem for Item {
911 /// type Key<'a> = &'a str;
912 /// fn key(&self) -> Self::Key<'_> {
913 /// &self.id
914 /// }
915 /// id_upcast!();
916 /// }
917 ///
918 /// let mut map = IdHashMap::new();
919 /// map.insert_unique(Item { id: "foo".to_string(), value: 42 }).unwrap();
920 ///
921 /// if let Some(mut item) = map.get_mut("foo") {
922 /// item.value = 100;
923 /// }
924 ///
925 /// assert_eq!(map.get("foo").unwrap().value, 100);
926 /// assert!(map.get_mut("bar").is_none());
927 /// # }
928 /// ```
929 pub fn get_mut<'a, Q>(&'a mut self, key: &Q) -> Option<RefMut<'a, T, S>>
930 where
931 Q: ?Sized + Hash + Equivalent<T::Key<'a>>,
932 {
933 let (dormant_map, index) = {
934 let (map, dormant_map) = DormantMutRef::new(self);
935 let index = map.find_index(key)?;
936 (dormant_map, index)
937 };
938
939 // SAFETY: `map` is not used after this point.
940 let awakened_map = unsafe { dormant_map.awaken() };
941 let item = &mut awakened_map.items[index];
942 let state = awakened_map.tables.state.clone();
943 let hashes = awakened_map.tables.make_hash(item);
944 Some(RefMut::new(state, hashes, item))
945 }
946
947 /// Removes an item from the map by its key.
948 ///
949 /// # Examples
950 ///
951 /// ```
952 /// # #[cfg(feature = "default-hasher")] {
953 /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
954 ///
955 /// #[derive(Debug, PartialEq, Eq, Hash)]
956 /// struct Item {
957 /// id: String,
958 /// value: u32,
959 /// }
960 ///
961 /// impl IdHashItem for Item {
962 /// type Key<'a> = &'a str;
963 /// fn key(&self) -> Self::Key<'_> {
964 /// &self.id
965 /// }
966 /// id_upcast!();
967 /// }
968 ///
969 /// let mut map = IdHashMap::new();
970 /// map.insert_unique(Item { id: "foo".to_string(), value: 42 }).unwrap();
971 ///
972 /// let removed = map.remove("foo");
973 /// assert_eq!(removed.unwrap().value, 42);
974 /// assert!(map.is_empty());
975 ///
976 /// // Removing non-existent key returns None
977 /// assert!(map.remove("bar").is_none());
978 /// # }
979 /// ```
980 pub fn remove<'a, Q>(&'a mut self, key: &Q) -> Option<T>
981 where
982 Q: ?Sized + Hash + Equivalent<T::Key<'a>>,
983 {
984 let (dormant_map, remove_index) = {
985 let (map, dormant_map) = DormantMutRef::new(self);
986 let remove_index = map.find_index(key)?;
987 (dormant_map, remove_index)
988 };
989
990 // SAFETY: `map` is not used after this point.
991 let awakened_map = unsafe { dormant_map.awaken() };
992
993 let value = awakened_map
994 .items
995 .remove(remove_index)
996 .expect("items missing key1 that was just retrieved");
997
998 // Remove the value from the tables.
999 let state = &awakened_map.tables.state;
1000 let Ok(item1) = awakened_map.tables.key_to_item.find_entry(
1001 state,
1002 &value.key(),
1003 |index| {
1004 if index == remove_index {
1005 value.key()
1006 } else {
1007 awakened_map.items[index].key()
1008 }
1009 },
1010 ) else {
1011 // The item was not found.
1012 panic!("we just looked this item up");
1013 };
1014
1015 item1.remove();
1016
1017 Some(value)
1018 }
1019
1020 /// Retrieves an entry by its key.
1021 ///
1022 /// Due to borrow checker limitations, this always accepts an owned key
1023 /// rather than a borrowed form of it.
1024 ///
1025 /// # Examples
1026 ///
1027 /// ```
1028 /// # #[cfg(feature = "default-hasher")] {
1029 /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
1030 ///
1031 /// #[derive(Debug, PartialEq, Eq, Hash)]
1032 /// struct Item {
1033 /// id: String,
1034 /// value: u32,
1035 /// }
1036 ///
1037 /// impl IdHashItem for Item {
1038 /// type Key<'a> = &'a str;
1039 /// fn key(&self) -> Self::Key<'_> {
1040 /// &self.id
1041 /// }
1042 /// id_upcast!();
1043 /// }
1044 ///
1045 /// let mut map = IdHashMap::new();
1046 ///
1047 /// // Use entry API for conditional insertion
1048 /// map.entry("foo").or_insert(Item { id: "foo".to_string(), value: 42 });
1049 /// map.entry("bar").or_insert(Item { id: "bar".to_string(), value: 20 });
1050 ///
1051 /// assert_eq!(map.len(), 2);
1052 /// # }
1053 /// ```
1054 pub fn entry<'a>(&'a mut self, key: T::Key<'_>) -> Entry<'a, T, S, A> {
1055 // Why does this always take an owned key? Well, it would seem like we
1056 // should be able to pass in any Q that is equivalent. That results in
1057 // *this* code compiling fine, but callers have trouble using it because
1058 // the borrow checker believes the keys are borrowed for the full 'a
1059 // rather than a shorter lifetime.
1060 //
1061 // By accepting owned keys, we can use the upcast functions to convert
1062 // them to a shorter lifetime (so this function accepts T::Key<'_>
1063 // rather than T::Key<'a>).
1064 //
1065 // Really, the solution here is to allow GATs to require covariant
1066 // parameters. If that were allowed, the borrow checker should be able
1067 // to figure out that keys don't need to be borrowed for the full 'a,
1068 // just for some shorter lifetime.
1069 let (map, dormant_map) = DormantMutRef::new(self);
1070 let key = T::upcast_key(key);
1071 {
1072 // index is explicitly typed to show that it has a trivial Drop impl
1073 // that doesn't capture anything from map.
1074 let index: Option<usize> = map.tables.key_to_item.find_index(
1075 &map.tables.state,
1076 &key,
1077 |index| map.items[index].key(),
1078 );
1079 if let Some(index) = index {
1080 drop(key);
1081 return Entry::Occupied(
1082 // SAFETY: `map` is not used after this point.
1083 unsafe { OccupiedEntry::new(dormant_map, index) },
1084 );
1085 }
1086 }
1087 let hash = map.make_key_hash(&key);
1088 Entry::Vacant(
1089 // SAFETY: `map` is not used after this point.
1090 unsafe { VacantEntry::new(dormant_map, hash) },
1091 )
1092 }
1093
1094 /// Retains only the elements specified by the predicate.
1095 ///
1096 /// In other words, remove all items `T` for which `f(RefMut<T>)` returns
1097 /// false. The elements are visited in an arbitrary order.
1098 ///
1099 /// # Examples
1100 ///
1101 /// ```
1102 /// # #[cfg(feature = "default-hasher")] {
1103 /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
1104 ///
1105 /// #[derive(Debug, PartialEq, Eq, Hash)]
1106 /// struct Item {
1107 /// id: String,
1108 /// value: u32,
1109 /// }
1110 ///
1111 /// impl IdHashItem for Item {
1112 /// type Key<'a> = &'a str;
1113 ///
1114 /// fn key(&self) -> Self::Key<'_> {
1115 /// &self.id
1116 /// }
1117 ///
1118 /// id_upcast!();
1119 /// }
1120 ///
1121 /// let mut map = IdHashMap::new();
1122 /// map.insert_unique(Item { id: "foo".to_string(), value: 42 }).unwrap();
1123 /// map.insert_unique(Item { id: "bar".to_string(), value: 20 }).unwrap();
1124 /// map.insert_unique(Item { id: "baz".to_string(), value: 99 }).unwrap();
1125 ///
1126 /// // Retain only items where value is greater than 30
1127 /// map.retain(|item| item.value > 30);
1128 ///
1129 /// assert_eq!(map.len(), 2);
1130 /// assert_eq!(map.get("foo").unwrap().value, 42);
1131 /// assert_eq!(map.get("baz").unwrap().value, 99);
1132 /// assert!(map.get("bar").is_none());
1133 /// # }
1134 /// ```
1135 pub fn retain<'a, F>(&'a mut self, mut f: F)
1136 where
1137 F: FnMut(RefMut<'a, T, S>) -> bool,
1138 {
1139 let hash_state = self.tables.state.clone();
1140 let (_, mut dormant_items) = DormantMutRef::new(&mut self.items);
1141
1142 self.tables.key_to_item.retain(|index| {
1143 let (item, dormant_items) = {
1144 // SAFETY: All uses of `items` ended in the previous iteration.
1145 let items = unsafe { dormant_items.reborrow() };
1146 let (items, dormant_items) = DormantMutRef::new(items);
1147 let item: &'a mut T = items
1148 .get_mut(index)
1149 .expect("all indexes are present in self.items");
1150 (item, dormant_items)
1151 };
1152
1153 let (hash, dormant_item) = {
1154 let (item, dormant_item): (&'a mut T, _) =
1155 DormantMutRef::new(item);
1156 // Use T::key(item) rather than item.key() to force the key
1157 // trait function to be called for T rather than &mut T.
1158 let key = T::key(item);
1159 let hash = hash_state.hash_one(key);
1160 (MapHash::new(hash), dormant_item)
1161 };
1162
1163 // SAFETY: The original items is no longer used after the first
1164 // block above.
1165 let items = unsafe { dormant_items.awaken() };
1166 // SAFETY: The original item is no longer used after the second
1167 // block above.
1168 let item = unsafe { dormant_item.awaken() };
1169
1170 let ref_mut = RefMut::new(hash_state.clone(), hash, item);
1171 if f(ref_mut) {
1172 true
1173 } else {
1174 items.remove(index);
1175 false
1176 }
1177 });
1178 }
1179
1180 fn find_index<'a, Q>(&'a self, k: &Q) -> Option<usize>
1181 where
1182 Q: Hash + Equivalent<T::Key<'a>> + ?Sized,
1183 {
1184 self.tables
1185 .key_to_item
1186 .find_index(&self.tables.state, k, |index| self.items[index].key())
1187 }
1188
1189 fn make_hash(&self, item: &T) -> MapHash {
1190 self.tables.make_hash(item)
1191 }
1192
1193 fn make_key_hash(&self, key: &T::Key<'_>) -> MapHash {
1194 self.tables.make_key_hash::<T>(key)
1195 }
1196
1197 pub(super) fn get_by_index(&self, index: usize) -> Option<&T> {
1198 self.items.get(index)
1199 }
1200
1201 pub(super) fn get_by_index_mut(
1202 &mut self,
1203 index: usize,
1204 ) -> Option<RefMut<'_, T, S>> {
1205 let state = self.tables.state.clone();
1206 let hashes = self.make_hash(&self.items[index]);
1207 let item = &mut self.items[index];
1208 Some(RefMut::new(state, hashes, item))
1209 }
1210
1211 pub(super) fn insert_unique_impl(
1212 &mut self,
1213 value: T,
1214 ) -> Result<usize, DuplicateItem<T, &T>> {
1215 let mut duplicates = BTreeSet::new();
1216
1217 // Check for duplicates *before* inserting the new item, because we
1218 // don't want to partially insert the new item and then have to roll
1219 // back.
1220 let key = value.key();
1221 let state = &self.tables.state;
1222
1223 let entry = match self
1224 .tables
1225 .key_to_item
1226 .entry(state, key, |index| self.items[index].key())
1227 {
1228 hash_table::Entry::Occupied(slot) => {
1229 duplicates.insert(*slot.get());
1230 None
1231 }
1232 hash_table::Entry::Vacant(slot) => Some(slot),
1233 };
1234
1235 if !duplicates.is_empty() {
1236 return Err(DuplicateItem::__internal_new(
1237 value,
1238 duplicates.iter().map(|ix| &self.items[*ix]).collect(),
1239 ));
1240 }
1241
1242 let next_index = self.items.insert_at_next_index(value);
1243 entry.unwrap().insert(next_index);
1244
1245 Ok(next_index)
1246 }
1247
1248 pub(super) fn remove_by_index(&mut self, remove_index: usize) -> Option<T> {
1249 let value = self.items.remove(remove_index)?;
1250
1251 // Remove the value from the tables.
1252 let state = &self.tables.state;
1253 let Ok(item) =
1254 self.tables.key_to_item.find_entry(state, &value.key(), |index| {
1255 if index == remove_index {
1256 value.key()
1257 } else {
1258 self.items[index].key()
1259 }
1260 })
1261 else {
1262 // The item was not found.
1263 panic!("we just looked this item up");
1264 };
1265
1266 item.remove();
1267
1268 Some(value)
1269 }
1270
1271 pub(super) fn replace_at_index(&mut self, index: usize, value: T) -> T {
1272 // We check the key before removing it, to avoid leaving the map in an
1273 // inconsistent state.
1274 let old_key =
1275 self.get_by_index(index).expect("index is known to be valid").key();
1276 if T::upcast_key(old_key) != value.key() {
1277 panic!(
1278 "must insert a value with \
1279 the same key used to create the entry"
1280 );
1281 }
1282
1283 // Now that we know the key is the same, we can replace the value
1284 // directly without needing to tweak any tables.
1285 self.items.replace(index, value)
1286 }
1287}
1288
1289impl<'a, T, S: Clone + BuildHasher, A: Allocator> fmt::Debug
1290 for IdHashMap<T, S, A>
1291where
1292 T: IdHashItem + fmt::Debug,
1293 T::Key<'a>: fmt::Debug,
1294 T: 'a,
1295{
1296 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1297 let mut map = f.debug_map();
1298
1299 for item in self.iter() {
1300 let key = item.key();
1301
1302 // SAFETY:
1303 //
1304 // * Lifetime extension: for a type T and two lifetime params 'a and
1305 // 'b, T<'a> and T<'b> aren't guaranteed to have the same layout,
1306 // but (a) that is true today and (b) it would be shocking and
1307 // break half the Rust ecosystem if that were to change in the
1308 // future.
1309 // * We only use key within the scope of this block before immediately
1310 // dropping it. In particular, map.entry calls key.fmt() without
1311 // holding a reference to it.
1312 let key: T::Key<'a> =
1313 unsafe { core::mem::transmute::<T::Key<'_>, T::Key<'a>>(key) };
1314
1315 map.entry(&key, item);
1316 }
1317 map.finish()
1318 }
1319}
1320
1321impl<T: IdHashItem + PartialEq, S: Clone + BuildHasher, A: Allocator> PartialEq
1322 for IdHashMap<T, S, A>
1323{
1324 fn eq(&self, other: &Self) -> bool {
1325 // Implementing PartialEq for IdHashMap is tricky because IdHashMap is
1326 // not semantically like an IndexMap: two maps are equivalent even if
1327 // their items are in a different order. In other words, any permutation
1328 // of items is equivalent.
1329 //
1330 // We also can't sort the items because they're not necessarily Ord.
1331 //
1332 // So we write a custom equality check that checks that each key in one
1333 // map points to the same item as in the other map.
1334
1335 if self.items.len() != other.items.len() {
1336 return false;
1337 }
1338
1339 // Walk over all the items in the first map and check that they point to
1340 // the same item in the second map.
1341 for item in self.items.values() {
1342 let k1 = item.key();
1343
1344 // Check that the indexes are the same in the other map.
1345 let Some(other_ix) = other.find_index(&k1) else {
1346 return false;
1347 };
1348
1349 // Check that the other map's item is the same as this map's
1350 // item. (This is what we use the `PartialEq` bound on T for.)
1351 //
1352 // Because we've checked that other_ix is Some, we know that it is
1353 // valid and points to the expected item.
1354 let other_item = &other.items[other_ix];
1355 if item != other_item {
1356 return false;
1357 }
1358 }
1359
1360 true
1361 }
1362}
1363
1364// The Eq bound on T ensures that the TriHashMap forms an equivalence class.
1365impl<T: IdHashItem + Eq, S: Clone + BuildHasher, A: Allocator> Eq
1366 for IdHashMap<T, S, A>
1367{
1368}
1369
1370/// The `Extend` implementation overwrites duplicates. In the future, there will
1371/// also be an `extend_unique` method that will return an error.
1372///
1373/// # Examples
1374///
1375/// ```
1376/// # #[cfg(feature = "default-hasher")] {
1377/// use iddqd::{IdHashItem, IdHashMap, id_upcast};
1378///
1379/// #[derive(Debug, PartialEq, Eq, Hash)]
1380/// struct Item {
1381/// id: String,
1382/// value: u32,
1383/// }
1384///
1385/// impl IdHashItem for Item {
1386/// type Key<'a> = &'a str;
1387/// fn key(&self) -> Self::Key<'_> {
1388/// &self.id
1389/// }
1390/// id_upcast!();
1391/// }
1392///
1393/// let mut map = IdHashMap::new();
1394/// map.insert_unique(Item { id: "foo".to_string(), value: 42 }).unwrap();
1395///
1396/// let new_items = vec![
1397/// Item { id: "foo".to_string(), value: 100 }, // overwrites existing
1398/// Item { id: "bar".to_string(), value: 20 }, // new item
1399/// ];
1400///
1401/// map.extend(new_items);
1402/// assert_eq!(map.len(), 2);
1403/// assert_eq!(map.get("foo").unwrap().value, 100); // overwritten
1404/// assert_eq!(map.get("bar").unwrap().value, 20); // new
1405///
1406/// # }
1407/// ```
1408impl<T: IdHashItem, S: Clone + BuildHasher, A: Allocator> Extend<T>
1409 for IdHashMap<T, S, A>
1410{
1411 fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
1412 for item in iter {
1413 self.insert_overwrite(item);
1414 }
1415 }
1416}
1417
1418impl<'a, T: IdHashItem, S: Clone + BuildHasher, A: Allocator> IntoIterator
1419 for &'a IdHashMap<T, S, A>
1420{
1421 type Item = &'a T;
1422 type IntoIter = Iter<'a, T>;
1423
1424 /// Creates an iterator over references to the items in the map.
1425 ///
1426 /// # Examples
1427 ///
1428 /// ```
1429 /// # #[cfg(feature = "default-hasher")] {
1430 /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
1431 ///
1432 /// #[derive(Debug, PartialEq, Eq, Hash)]
1433 /// struct Item {
1434 /// id: String,
1435 /// value: u32,
1436 /// }
1437 ///
1438 /// impl IdHashItem for Item {
1439 /// type Key<'a> = &'a str;
1440 /// fn key(&self) -> Self::Key<'_> {
1441 /// &self.id
1442 /// }
1443 /// id_upcast!();
1444 /// }
1445 ///
1446 /// let mut map = IdHashMap::new();
1447 /// map.insert_unique(Item { id: "foo".to_string(), value: 42 }).unwrap();
1448 /// map.insert_unique(Item { id: "bar".to_string(), value: 20 }).unwrap();
1449 ///
1450 /// let mut values: Vec<u32> =
1451 /// (&map).into_iter().map(|item| item.value).collect();
1452 /// values.sort();
1453 /// assert_eq!(values, vec![20, 42]);
1454 /// # }
1455 /// ```
1456 #[inline]
1457 fn into_iter(self) -> Self::IntoIter {
1458 self.iter()
1459 }
1460}
1461
1462impl<'a, T: IdHashItem, S: Clone + BuildHasher, A: Allocator> IntoIterator
1463 for &'a mut IdHashMap<T, S, A>
1464{
1465 type Item = RefMut<'a, T, S>;
1466 type IntoIter = IterMut<'a, T, S, A>;
1467
1468 /// Creates an iterator over mutable references to the items in the map.
1469 ///
1470 /// # Examples
1471 ///
1472 /// ```
1473 /// # #[cfg(feature = "default-hasher")] {
1474 /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
1475 ///
1476 /// #[derive(Debug, PartialEq, Eq, Hash)]
1477 /// struct Item {
1478 /// id: String,
1479 /// value: u32,
1480 /// }
1481 ///
1482 /// impl IdHashItem for Item {
1483 /// type Key<'a> = &'a str;
1484 /// fn key(&self) -> Self::Key<'_> {
1485 /// &self.id
1486 /// }
1487 /// id_upcast!();
1488 /// }
1489 ///
1490 /// let mut map = IdHashMap::new();
1491 /// map.insert_unique(Item { id: "foo".to_string(), value: 42 }).unwrap();
1492 /// map.insert_unique(Item { id: "bar".to_string(), value: 20 }).unwrap();
1493 ///
1494 /// for mut item in &mut map {
1495 /// item.value *= 2;
1496 /// }
1497 ///
1498 /// assert_eq!(map.get("foo").unwrap().value, 84);
1499 /// assert_eq!(map.get("bar").unwrap().value, 40);
1500 /// # }
1501 /// ```
1502 #[inline]
1503 fn into_iter(self) -> Self::IntoIter {
1504 self.iter_mut()
1505 }
1506}
1507
1508impl<T: IdHashItem, S: Clone + BuildHasher, A: Allocator> IntoIterator
1509 for IdHashMap<T, S, A>
1510{
1511 type Item = T;
1512 type IntoIter = IntoIter<T, A>;
1513
1514 /// Consumes the map and creates an iterator over the owned items.
1515 ///
1516 /// # Examples
1517 ///
1518 /// ```
1519 /// # #[cfg(feature = "default-hasher")] {
1520 /// use iddqd::{IdHashItem, IdHashMap, id_upcast};
1521 ///
1522 /// #[derive(Debug, PartialEq, Eq, Hash)]
1523 /// struct Item {
1524 /// id: String,
1525 /// value: u32,
1526 /// }
1527 ///
1528 /// impl IdHashItem for Item {
1529 /// type Key<'a> = &'a str;
1530 /// fn key(&self) -> Self::Key<'_> {
1531 /// &self.id
1532 /// }
1533 /// id_upcast!();
1534 /// }
1535 ///
1536 /// let mut map = IdHashMap::new();
1537 /// map.insert_unique(Item { id: "foo".to_string(), value: 42 }).unwrap();
1538 /// map.insert_unique(Item { id: "bar".to_string(), value: 20 }).unwrap();
1539 ///
1540 /// let mut values: Vec<u32> = map.into_iter().map(|item| item.value).collect();
1541 /// values.sort();
1542 /// assert_eq!(values, vec![20, 42]);
1543 /// # }
1544 /// ```
1545 #[inline]
1546 fn into_iter(self) -> Self::IntoIter {
1547 IntoIter::new(self.items)
1548 }
1549}
1550
1551/// The `FromIterator` implementation for `IdHashMap` overwrites duplicate
1552/// items.
1553///
1554/// # Examples
1555///
1556/// ```
1557/// # #[cfg(feature = "default-hasher")] {
1558/// use iddqd::{IdHashItem, IdHashMap, id_upcast};
1559///
1560/// #[derive(Debug, PartialEq, Eq, Hash)]
1561/// struct Item {
1562/// id: String,
1563/// value: u32,
1564/// }
1565///
1566/// impl IdHashItem for Item {
1567/// type Key<'a> = &'a str;
1568/// fn key(&self) -> Self::Key<'_> {
1569/// &self.id
1570/// }
1571/// id_upcast!();
1572/// }
1573///
1574/// let items = vec![
1575/// Item { id: "foo".to_string(), value: 42 },
1576/// Item { id: "bar".to_string(), value: 20 },
1577/// Item { id: "foo".to_string(), value: 100 }, // duplicate key, overwrites
1578/// ];
1579///
1580/// let map: IdHashMap<Item> = items.into_iter().collect();
1581/// assert_eq!(map.len(), 2);
1582/// assert_eq!(map.get("foo").unwrap().value, 100); // last value wins
1583/// assert_eq!(map.get("bar").unwrap().value, 20);
1584/// # }
1585/// ```
1586impl<T: IdHashItem, S: Default + Clone + BuildHasher, A: Allocator + Default>
1587 FromIterator<T> for IdHashMap<T, S, A>
1588{
1589 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
1590 let mut map = IdHashMap::default();
1591 for item in iter {
1592 map.insert_overwrite(item);
1593 }
1594 map
1595 }
1596}