iddqd/id_ord_map/imp.rs
1use super::{
2 Entry, IdOrdItem, IntoIter, Iter, IterMut, OccupiedEntry, RefMut,
3 VacantEntry, tables::IdOrdMapTables,
4};
5use crate::{
6 errors::DuplicateItem,
7 internal::{ValidateChaos, ValidateCompact, ValidationError},
8 support::{
9 alloc::{Global, global_alloc},
10 borrow::DormantMutRef,
11 item_set::ItemSet,
12 },
13};
14use alloc::collections::BTreeSet;
15use core::{fmt, hash::Hash};
16use equivalent::{Comparable, Equivalent};
17
18/// An ordered map where the keys are part of the values, based on a B-Tree.
19///
20/// The storage mechanism is a fast hash table of integer indexes to items, with
21/// the indexes stored in a B-Tree map.
22///
23/// # Examples
24///
25/// ```
26/// # #[cfg(feature = "default-hasher")] {
27/// use iddqd::{IdOrdItem, IdOrdMap, id_upcast};
28///
29/// // Define a struct with a key.
30/// #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
31/// struct MyItem {
32/// id: String,
33/// value: u32,
34/// }
35///
36/// // Implement IdOrdItem for the struct.
37/// impl IdOrdItem for MyItem {
38/// // Keys can borrow from the item.
39/// type Key<'a> = &'a str;
40///
41/// fn key(&self) -> Self::Key<'_> {
42/// &self.id
43/// }
44///
45/// id_upcast!();
46/// }
47///
48/// // Create an IdOrdMap and insert items.
49/// let mut map = IdOrdMap::new();
50/// map.insert_unique(MyItem { id: "foo".to_string(), value: 42 }).unwrap();
51/// map.insert_unique(MyItem { id: "bar".to_string(), value: 20 }).unwrap();
52///
53/// // Look up items by their keys.
54/// assert_eq!(map.get("foo").unwrap().value, 42);
55/// assert_eq!(map.get("bar").unwrap().value, 20);
56/// assert!(map.get("baz").is_none());
57/// # }
58/// ```
59#[derive(Clone)]
60pub struct IdOrdMap<T: IdOrdItem> {
61 // We don't expose an allocator trait here because it isn't stable with
62 // std's BTreeMap.
63 pub(super) items: ItemSet<T, Global>,
64 // Invariant: the values (usize) in these tables are valid indexes into
65 // `items`, and are a 1:1 mapping.
66 pub(super) tables: IdOrdMapTables,
67}
68
69impl<T: IdOrdItem> Default for IdOrdMap<T> {
70 fn default() -> Self {
71 Self::new()
72 }
73}
74
75impl<T: IdOrdItem> IdOrdMap<T> {
76 /// Creates a new, empty `IdOrdMap`.
77 ///
78 /// # Examples
79 ///
80 /// ```
81 /// use iddqd::{IdOrdItem, IdOrdMap, id_upcast};
82 ///
83 /// #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
84 /// struct Item {
85 /// id: String,
86 /// value: u32,
87 /// }
88 ///
89 /// impl IdOrdItem for Item {
90 /// type Key<'a> = &'a str;
91 ///
92 /// fn key(&self) -> Self::Key<'_> {
93 /// &self.id
94 /// }
95 ///
96 /// id_upcast!();
97 /// }
98 ///
99 /// let map: IdOrdMap<Item> = IdOrdMap::new();
100 /// assert!(map.is_empty());
101 /// assert_eq!(map.len(), 0);
102 /// ```
103 #[inline]
104 pub fn new() -> Self {
105 Self { items: ItemSet::default(), tables: IdOrdMapTables::new() }
106 }
107
108 /// Creates a new `IdOrdMap` with the given capacity.
109 ///
110 /// The capacity will be used to initialize the underlying hash table.
111 ///
112 /// # Examples
113 ///
114 /// ```
115 /// use iddqd::{IdOrdItem, IdOrdMap, id_upcast};
116 ///
117 /// #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
118 /// struct Item {
119 /// id: String,
120 /// value: u32,
121 /// }
122 ///
123 /// impl IdOrdItem for Item {
124 /// type Key<'a> = &'a str;
125 ///
126 /// fn key(&self) -> Self::Key<'_> {
127 /// &self.id
128 /// }
129 ///
130 /// id_upcast!();
131 /// }
132 ///
133 /// let map: IdOrdMap<Item> = IdOrdMap::with_capacity(10);
134 /// assert!(map.capacity() >= 10);
135 /// assert!(map.is_empty());
136 /// ```
137 pub fn with_capacity(capacity: usize) -> Self {
138 Self {
139 items: ItemSet::with_capacity_in(capacity, global_alloc()),
140 tables: IdOrdMapTables::new(),
141 }
142 }
143
144 /// Returns the currently allocated capacity of the map.
145 ///
146 /// # Examples
147 ///
148 /// ```
149 /// use iddqd::{IdOrdItem, IdOrdMap, id_upcast};
150 ///
151 /// #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
152 /// struct Item {
153 /// id: String,
154 /// value: u32,
155 /// }
156 ///
157 /// impl IdOrdItem for Item {
158 /// type Key<'a> = &'a str;
159 ///
160 /// fn key(&self) -> Self::Key<'_> {
161 /// &self.id
162 /// }
163 ///
164 /// id_upcast!();
165 /// }
166 ///
167 /// let map: IdOrdMap<Item> = IdOrdMap::with_capacity(10);
168 /// assert!(map.capacity() >= 10);
169 /// ```
170 pub fn capacity(&self) -> usize {
171 // There's no self.tables.capacity.
172 self.items.capacity()
173 }
174
175 /// Constructs a new `IdOrdMap` from an iterator of values, rejecting
176 /// duplicates.
177 ///
178 /// To overwrite duplicates instead, use [`IdOrdMap::from_iter`].
179 ///
180 /// # Examples
181 ///
182 /// ```
183 /// use iddqd::{IdOrdItem, IdOrdMap, id_upcast};
184 ///
185 /// #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
186 /// struct Item {
187 /// id: String,
188 /// value: u32,
189 /// }
190 ///
191 /// impl IdOrdItem for Item {
192 /// type Key<'a> = &'a str;
193 ///
194 /// fn key(&self) -> Self::Key<'_> {
195 /// &self.id
196 /// }
197 ///
198 /// id_upcast!();
199 /// }
200 ///
201 /// let items = vec![
202 /// Item { id: "foo".to_string(), value: 42 },
203 /// Item { id: "bar".to_string(), value: 99 },
204 /// ];
205 ///
206 /// // Successful creation with unique keys
207 /// let map = IdOrdMap::from_iter_unique(items).unwrap();
208 /// assert_eq!(map.len(), 2);
209 /// assert_eq!(map.get("foo").unwrap().value, 42);
210 ///
211 /// // Error with duplicate keys
212 /// let duplicate_items = vec![
213 /// Item { id: "foo".to_string(), value: 42 },
214 /// Item { id: "foo".to_string(), value: 99 },
215 /// ];
216 /// assert!(IdOrdMap::from_iter_unique(duplicate_items).is_err());
217 /// ```
218 pub fn from_iter_unique<I: IntoIterator<Item = T>>(
219 iter: I,
220 ) -> Result<Self, DuplicateItem<T>> {
221 let mut map = IdOrdMap::new();
222 for value in iter {
223 // It would be nice to use insert_overwrite here, but that would
224 // return a `DuplicateItem<T, &T>`, which can only be converted into
225 // an owned value if T: Clone. Doing this via the Entry API means we
226 // can return a `DuplicateItem<T>` without requiring T to be Clone.
227 match map.entry(value.key()) {
228 Entry::Occupied(entry) => {
229 let duplicate = entry.remove();
230 return Err(DuplicateItem::__internal_new(
231 value,
232 vec![duplicate],
233 ));
234 }
235 Entry::Vacant(entry) => {
236 entry.insert_ref(value);
237 }
238 }
239 }
240
241 Ok(map)
242 }
243
244 /// Returns true if the map is empty.
245 ///
246 /// # Examples
247 ///
248 /// ```
249 /// use iddqd::{IdOrdItem, IdOrdMap, id_upcast};
250 ///
251 /// #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
252 /// struct Item {
253 /// id: String,
254 /// value: u32,
255 /// }
256 ///
257 /// impl IdOrdItem for Item {
258 /// type Key<'a> = &'a str;
259 ///
260 /// fn key(&self) -> Self::Key<'_> {
261 /// &self.id
262 /// }
263 ///
264 /// id_upcast!();
265 /// }
266 ///
267 /// let mut map = IdOrdMap::new();
268 /// assert!(map.is_empty());
269 ///
270 /// map.insert_unique(Item { id: "foo".to_string(), value: 42 }).unwrap();
271 /// assert!(!map.is_empty());
272 /// ```
273 #[inline]
274 pub fn is_empty(&self) -> bool {
275 self.items.is_empty()
276 }
277
278 /// Returns the number of items in the map.
279 ///
280 /// # Examples
281 ///
282 /// ```
283 /// use iddqd::{IdOrdItem, IdOrdMap, id_upcast};
284 ///
285 /// #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
286 /// struct Item {
287 /// id: String,
288 /// value: u32,
289 /// }
290 ///
291 /// impl IdOrdItem for Item {
292 /// type Key<'a> = &'a str;
293 ///
294 /// fn key(&self) -> Self::Key<'_> {
295 /// &self.id
296 /// }
297 ///
298 /// id_upcast!();
299 /// }
300 ///
301 /// let mut map = IdOrdMap::new();
302 /// assert_eq!(map.len(), 0);
303 ///
304 /// map.insert_unique(Item { id: "foo".to_string(), value: 42 }).unwrap();
305 /// map.insert_unique(Item { id: "bar".to_string(), value: 99 }).unwrap();
306 /// assert_eq!(map.len(), 2);
307 /// ```
308 #[inline]
309 pub fn len(&self) -> usize {
310 self.items.len()
311 }
312
313 /// Iterates over the items in the map.
314 ///
315 /// Similar to [`BTreeMap`], the iteration is ordered by [`T::Key`].
316 ///
317 /// # Examples
318 ///
319 /// ```
320 /// use iddqd::{IdOrdItem, IdOrdMap, id_upcast};
321 ///
322 /// #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
323 /// struct Item {
324 /// id: String,
325 /// value: u32,
326 /// }
327 ///
328 /// impl IdOrdItem for Item {
329 /// type Key<'a> = &'a str;
330 ///
331 /// fn key(&self) -> Self::Key<'_> {
332 /// &self.id
333 /// }
334 ///
335 /// id_upcast!();
336 /// }
337 ///
338 /// let mut map = IdOrdMap::new();
339 /// map.insert_unique(Item { id: "charlie".to_string(), value: 30 }).unwrap();
340 /// map.insert_unique(Item { id: "alice".to_string(), value: 42 }).unwrap();
341 /// map.insert_unique(Item { id: "bob".to_string(), value: 99 }).unwrap();
342 ///
343 /// // Iteration is ordered by key
344 /// let mut iter = map.iter();
345 /// let item = iter.next().unwrap();
346 /// assert_eq!(item.id, "alice");
347 /// let item = iter.next().unwrap();
348 /// assert_eq!(item.id, "bob");
349 /// let item = iter.next().unwrap();
350 /// assert_eq!(item.id, "charlie");
351 /// assert!(iter.next().is_none());
352 /// ```
353 ///
354 /// [`BTreeMap`]: std::collections::BTreeMap
355 /// [`T::Key`]: crate::IdOrdItem::Key
356 #[inline]
357 pub fn iter(&self) -> Iter<'_, T> {
358 Iter::new(&self.items, &self.tables)
359 }
360
361 /// Iterates over the items in the map, allowing for mutation.
362 ///
363 /// Similar to [`BTreeMap`], the iteration is ordered by [`T::Key`].
364 ///
365 /// # Examples
366 ///
367 /// ```
368 /// use iddqd::{IdOrdItem, IdOrdMap, id_upcast};
369 ///
370 /// #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
371 /// struct Item {
372 /// id: String,
373 /// value: u32,
374 /// }
375 ///
376 /// impl IdOrdItem for Item {
377 /// type Key<'a> = &'a str;
378 ///
379 /// fn key(&self) -> Self::Key<'_> {
380 /// &self.id
381 /// }
382 ///
383 /// id_upcast!();
384 /// }
385 ///
386 /// let mut map = IdOrdMap::new();
387 /// map.insert_unique(Item { id: "foo".to_string(), value: 42 }).unwrap();
388 /// map.insert_unique(Item { id: "bar".to_string(), value: 99 }).unwrap();
389 ///
390 /// // Modify values through the mutable iterator
391 /// for mut item in map.iter_mut() {
392 /// item.value *= 2;
393 /// }
394 ///
395 /// assert_eq!(map.get("foo").unwrap().value, 84);
396 /// assert_eq!(map.get("bar").unwrap().value, 198);
397 /// ```
398 ///
399 /// [`BTreeMap`]: std::collections::BTreeMap
400 /// [`T::Key`]: crate::IdOrdItem::Key
401 #[inline]
402 pub fn iter_mut<'a>(&'a mut self) -> IterMut<'a, T>
403 where
404 T::Key<'a>: Hash,
405 {
406 IterMut::new(&mut self.items, &self.tables)
407 }
408
409 /// Checks general invariants of the map.
410 ///
411 /// The code below always upholds these invariants, but it's useful to have
412 /// an explicit check for tests.
413 #[doc(hidden)]
414 pub fn validate(
415 &self,
416 compactness: ValidateCompact,
417 chaos: ValidateChaos,
418 ) -> Result<(), ValidationError>
419 where
420 T: fmt::Debug,
421 {
422 self.items.validate(compactness)?;
423 self.tables.validate(self.len(), compactness)?;
424
425 // Check that the indexes are all correct.
426
427 for (&ix, item) in self.items.iter() {
428 let key = item.key();
429 let ix1 = match chaos {
430 ValidateChaos::Yes => {
431 // Fall back to a linear search.
432 self.linear_search_index(&key)
433 }
434 ValidateChaos::No => {
435 // Use the B-Tree table to find the index.
436 self.find_index(&key)
437 }
438 };
439 let Some(ix1) = ix1 else {
440 return Err(ValidationError::general(format!(
441 "item at index {ix} has no key1 index"
442 )));
443 };
444
445 if ix1 != ix {
446 return Err(ValidationError::General(format!(
447 "item at index {ix} has mismatched indexes: ix1: {ix1}",
448 )));
449 }
450 }
451
452 Ok(())
453 }
454
455 /// Inserts a value into the set, returning an error if any duplicates were
456 /// added.
457 ///
458 /// # Examples
459 ///
460 /// ```
461 /// use iddqd::{IdOrdItem, IdOrdMap, id_upcast};
462 ///
463 /// #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
464 /// struct Item {
465 /// id: String,
466 /// value: u32,
467 /// }
468 ///
469 /// impl IdOrdItem for Item {
470 /// type Key<'a> = &'a str;
471 ///
472 /// fn key(&self) -> Self::Key<'_> {
473 /// &self.id
474 /// }
475 ///
476 /// id_upcast!();
477 /// }
478 ///
479 /// let mut map = IdOrdMap::new();
480 ///
481 /// // Successful insertion
482 /// assert!(
483 /// map.insert_unique(Item { id: "foo".to_string(), value: 42 }).is_ok()
484 /// );
485 /// assert!(
486 /// map.insert_unique(Item { id: "bar".to_string(), value: 99 }).is_ok()
487 /// );
488 ///
489 /// // Duplicate key
490 /// assert!(
491 /// map.insert_unique(Item { id: "foo".to_string(), value: 100 }).is_err()
492 /// );
493 /// ```
494 pub fn insert_unique(
495 &mut self,
496 value: T,
497 ) -> Result<(), DuplicateItem<T, &T>> {
498 let _ = self.insert_unique_impl(value)?;
499 Ok(())
500 }
501
502 /// Inserts a value into the map, removing and returning the conflicting
503 /// item, if any.
504 ///
505 /// # Examples
506 ///
507 /// ```
508 /// use iddqd::{IdOrdItem, IdOrdMap, id_upcast};
509 ///
510 /// #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
511 /// struct Item {
512 /// id: String,
513 /// value: u32,
514 /// }
515 ///
516 /// impl IdOrdItem for Item {
517 /// type Key<'a> = &'a str;
518 ///
519 /// fn key(&self) -> Self::Key<'_> {
520 /// &self.id
521 /// }
522 ///
523 /// id_upcast!();
524 /// }
525 ///
526 /// let mut map = IdOrdMap::new();
527 ///
528 /// // First insertion - no conflict
529 /// let old = map.insert_overwrite(Item { id: "foo".to_string(), value: 42 });
530 /// assert!(old.is_none());
531 ///
532 /// // Overwrite existing key - returns old value
533 /// let old = map.insert_overwrite(Item { id: "foo".to_string(), value: 99 });
534 /// assert!(old.is_some());
535 /// assert_eq!(old.unwrap().value, 42);
536 ///
537 /// // Verify new value is in the map
538 /// assert_eq!(map.get("foo").unwrap().value, 99);
539 /// ```
540 #[doc(alias = "insert")]
541 pub fn insert_overwrite(&mut self, value: T) -> Option<T> {
542 // Trying to write this function for maximal efficiency can get very
543 // tricky, requiring delicate handling of indexes. We follow a very
544 // simple approach instead:
545 //
546 // 1. Remove the item corresponding to the key that is already in the map.
547 // 2. Add the item to the map.
548
549 let duplicate = self.remove(&value.key());
550
551 if self.insert_unique(value).is_err() {
552 // We should never get here, because we just removed all the
553 // duplicates.
554 panic!("insert_unique failed after removing duplicates");
555 }
556
557 duplicate
558 }
559
560 /// Returns true if the map contains the given `key`.
561 ///
562 /// # Examples
563 ///
564 /// ```
565 /// use iddqd::{IdOrdItem, IdOrdMap, id_upcast};
566 ///
567 /// #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
568 /// struct Item {
569 /// id: String,
570 /// value: u32,
571 /// }
572 ///
573 /// impl IdOrdItem for Item {
574 /// type Key<'a> = &'a str;
575 ///
576 /// fn key(&self) -> Self::Key<'_> {
577 /// &self.id
578 /// }
579 ///
580 /// id_upcast!();
581 /// }
582 ///
583 /// let mut map = IdOrdMap::new();
584 /// map.insert_unique(Item { id: "foo".to_string(), value: 42 }).unwrap();
585 ///
586 /// assert!(map.contains_key("foo"));
587 /// assert!(!map.contains_key("bar"));
588 /// ```
589 pub fn contains_key<'a, Q>(&'a self, key: &Q) -> bool
590 where
591 Q: ?Sized + Comparable<T::Key<'a>>,
592 {
593 self.find_index(key).is_some()
594 }
595
596 /// Gets a reference to the value associated with the given `key`.
597 ///
598 /// # Examples
599 ///
600 /// ```
601 /// use iddqd::{IdOrdItem, IdOrdMap, id_upcast};
602 ///
603 /// #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
604 /// struct Item {
605 /// id: String,
606 /// value: u32,
607 /// }
608 ///
609 /// impl IdOrdItem for Item {
610 /// type Key<'a> = &'a str;
611 ///
612 /// fn key(&self) -> Self::Key<'_> {
613 /// &self.id
614 /// }
615 ///
616 /// id_upcast!();
617 /// }
618 ///
619 /// let mut map = IdOrdMap::new();
620 /// map.insert_unique(Item { id: "foo".to_string(), value: 42 }).unwrap();
621 ///
622 /// assert_eq!(map.get("foo").unwrap().value, 42);
623 /// assert!(map.get("bar").is_none());
624 /// ```
625 pub fn get<'a, Q>(&'a self, key: &Q) -> Option<&'a T>
626 where
627 Q: ?Sized + Comparable<T::Key<'a>>,
628 {
629 self.find(key)
630 }
631
632 /// Gets a mutable reference to the item associated with the given `key`.
633 ///
634 /// # Examples
635 ///
636 /// ```
637 /// use iddqd::{IdOrdItem, IdOrdMap, id_upcast};
638 ///
639 /// #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
640 /// struct Item {
641 /// id: String,
642 /// value: u32,
643 /// }
644 ///
645 /// impl IdOrdItem for Item {
646 /// type Key<'a> = &'a str;
647 ///
648 /// fn key(&self) -> Self::Key<'_> {
649 /// &self.id
650 /// }
651 ///
652 /// id_upcast!();
653 /// }
654 ///
655 /// let mut map = IdOrdMap::new();
656 /// map.insert_unique(Item { id: "foo".to_string(), value: 42 }).unwrap();
657 ///
658 /// if let Some(mut item) = map.get_mut("foo") {
659 /// item.value = 99;
660 /// }
661 ///
662 /// assert_eq!(map.get("foo").unwrap().value, 99);
663 /// ```
664 pub fn get_mut<'a, Q>(&'a mut self, key: &Q) -> Option<RefMut<'a, T>>
665 where
666 Q: ?Sized + Comparable<T::Key<'a>>,
667 T::Key<'a>: Hash,
668 {
669 let (dormant_map, index) = {
670 let (map, dormant_map) = DormantMutRef::new(self);
671 let index = map.find_index(key)?;
672 (dormant_map, index)
673 };
674
675 // SAFETY: `map` is not used after this point.
676 let awakened_map = unsafe { dormant_map.awaken() };
677 let item = &mut awakened_map.items[index];
678 let (hash, dormant) = {
679 let (item, dormant) = DormantMutRef::new(item);
680 let hash = awakened_map.tables.make_hash(item);
681 (hash, dormant)
682 };
683
684 // SAFETY: the original item is not used after this point.
685 let item = unsafe { dormant.awaken() };
686 Some(RefMut::new(hash, item))
687 }
688
689 /// Removes an item from the map by its `key`.
690 ///
691 /// # Examples
692 ///
693 /// ```
694 /// use iddqd::{IdOrdItem, IdOrdMap, id_upcast};
695 ///
696 /// #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
697 /// struct Item {
698 /// id: String,
699 /// value: u32,
700 /// }
701 ///
702 /// impl IdOrdItem for Item {
703 /// type Key<'a> = &'a str;
704 ///
705 /// fn key(&self) -> Self::Key<'_> {
706 /// &self.id
707 /// }
708 ///
709 /// id_upcast!();
710 /// }
711 ///
712 /// let mut map = IdOrdMap::new();
713 /// map.insert_unique(Item { id: "foo".to_string(), value: 42 }).unwrap();
714 ///
715 /// let removed = map.remove("foo");
716 /// assert!(removed.is_some());
717 /// assert_eq!(removed.unwrap().value, 42);
718 /// assert!(map.is_empty());
719 ///
720 /// // Removing a non-existent key returns None
721 /// assert!(map.remove("bar").is_none());
722 /// ```
723 pub fn remove<'a, Q>(&'a mut self, key: &Q) -> Option<T>
724 where
725 Q: ?Sized + Comparable<T::Key<'a>>,
726 {
727 let (dormant_map, remove_index) = {
728 let (map, dormant_map) = DormantMutRef::new(self);
729 let remove_index = map.find_index(key)?;
730 (dormant_map, remove_index)
731 };
732
733 // SAFETY: `map` is not used after this point.
734 let awakened_map = unsafe { dormant_map.awaken() };
735 awakened_map.remove_by_index(remove_index)
736 }
737
738 /// Retrieves an entry by its `key`.
739 ///
740 /// Due to borrow checker limitations, this always accepts an owned key rather
741 /// than a borrowed form.
742 ///
743 /// # Examples
744 ///
745 /// ```
746 /// use iddqd::{IdOrdItem, IdOrdMap, id_ord_map, id_upcast};
747 ///
748 /// #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
749 /// struct Item {
750 /// id: String,
751 /// value: u32,
752 /// }
753 ///
754 /// impl IdOrdItem for Item {
755 /// type Key<'a> = &'a str;
756 ///
757 /// fn key(&self) -> Self::Key<'_> {
758 /// &self.id
759 /// }
760 ///
761 /// id_upcast!();
762 /// }
763 ///
764 /// let mut map = IdOrdMap::new();
765 ///
766 /// // Insert via vacant entry
767 /// match map.entry("foo") {
768 /// id_ord_map::Entry::Vacant(entry) => {
769 /// entry.insert(Item { id: "foo".to_string(), value: 42 });
770 /// }
771 /// id_ord_map::Entry::Occupied(_) => {}
772 /// }
773 ///
774 /// // Update via occupied entry
775 /// match map.entry("foo") {
776 /// id_ord_map::Entry::Occupied(mut entry) => {
777 /// entry.get_mut().value = 99;
778 /// }
779 /// id_ord_map::Entry::Vacant(_) => {}
780 /// }
781 ///
782 /// assert_eq!(map.get("foo").unwrap().value, 99);
783 /// ```
784 pub fn entry<'a>(&'a mut self, key: T::Key<'_>) -> Entry<'a, T> {
785 // Why does this always take an owned key? Well, it would seem like we
786 // should be able to pass in any Q that is equivalent. That results in
787 // *this* code compiling fine, but callers have trouble using it because
788 // the borrow checker believes the keys are borrowed for the full 'a
789 // rather than a shorter lifetime.
790 //
791 // By accepting owned keys, we can use the upcast functions to convert
792 // them to a shorter lifetime (so this function accepts T::Key<'_>
793 // rather than T::Key<'a>).
794 //
795 // Really, the solution here is to allow GATs to require covariant
796 // parameters. If that were allowed, the borrow checker should be able
797 // to figure out that keys don't need to be borrowed for the full 'a,
798 // just for some shorter lifetime.
799 let (map, dormant_map) = DormantMutRef::new(self);
800 let key = T::upcast_key(key);
801 {
802 // index is explicitly typed to show that it has a trivial Drop impl
803 // that doesn't capture anything from map.
804 let index: Option<usize> = map
805 .tables
806 .key_to_item
807 .find_index(&key, |index| map.items[index].key());
808 if let Some(index) = index {
809 drop(key);
810 return Entry::Occupied(
811 // SAFETY: `map` is not used after this point.
812 unsafe { OccupiedEntry::new(dormant_map, index) },
813 );
814 }
815 }
816 Entry::Vacant(
817 // SAFETY: `map` is not used after this point.
818 unsafe { VacantEntry::new(dormant_map) },
819 )
820 }
821
822 fn find<'a, Q>(&'a self, k: &Q) -> Option<&'a T>
823 where
824 Q: ?Sized + Comparable<T::Key<'a>>,
825 {
826 self.find_index(k).map(|ix| &self.items[ix])
827 }
828
829 fn linear_search_index<'a, Q>(&'a self, k: &Q) -> Option<usize>
830 where
831 Q: ?Sized + Ord + Equivalent<T::Key<'a>>,
832 {
833 self.items.iter().find_map(|(index, item)| {
834 (k.equivalent(&item.key())).then_some(*index)
835 })
836 }
837
838 fn find_index<'a, Q>(&'a self, k: &Q) -> Option<usize>
839 where
840 Q: ?Sized + Comparable<T::Key<'a>>,
841 {
842 self.tables.key_to_item.find_index(k, |index| self.items[index].key())
843 }
844
845 pub(super) fn get_by_index(&self, index: usize) -> Option<&T> {
846 self.items.get(index)
847 }
848
849 pub(super) fn get_by_index_mut<'a>(
850 &'a mut self,
851 index: usize,
852 ) -> Option<RefMut<'a, T>>
853 where
854 T::Key<'a>: Hash,
855 {
856 let (hash, dormant) = {
857 let item: &'a mut T = self.items.get_mut(index)?;
858 let (item, dormant) = DormantMutRef::new(item);
859 let hash = self.tables.make_hash(item);
860 (hash, dormant)
861 };
862
863 // SAFETY: item is no longer used after the above point.
864 let item = unsafe { dormant.awaken() };
865 Some(RefMut::new(hash, item))
866 }
867
868 pub(super) fn insert_unique_impl(
869 &mut self,
870 value: T,
871 ) -> Result<usize, DuplicateItem<T, &T>> {
872 let mut duplicates = BTreeSet::new();
873
874 // Check for duplicates *before* inserting the new item, because we
875 // don't want to partially insert the new item and then have to roll
876 // back.
877 let key = value.key();
878
879 if let Some(index) = self
880 .tables
881 .key_to_item
882 .find_index(&key, |index| self.items[index].key())
883 {
884 duplicates.insert(index);
885 }
886
887 if !duplicates.is_empty() {
888 drop(key);
889 return Err(DuplicateItem::__internal_new(
890 value,
891 duplicates.iter().map(|ix| &self.items[*ix]).collect(),
892 ));
893 }
894
895 let next_index = self.items.next_index();
896 self.tables
897 .key_to_item
898 .insert(next_index, &key, |index| self.items[index].key());
899 drop(key);
900 self.items.insert_at_next_index(value);
901
902 Ok(next_index)
903 }
904
905 pub(super) fn remove_by_index(&mut self, remove_index: usize) -> Option<T> {
906 let value = self.items.remove(remove_index)?;
907
908 // Remove the value from the table.
909 self.tables.key_to_item.remove(remove_index, value.key(), |index| {
910 if index == remove_index {
911 value.key()
912 } else {
913 self.items[index].key()
914 }
915 });
916
917 Some(value)
918 }
919
920 pub(super) fn replace_at_index(&mut self, index: usize, value: T) -> T {
921 // We check the key before removing it, to avoid leaving the map in an
922 // inconsistent state.
923 let old_key =
924 self.get_by_index(index).expect("index is known to be valid").key();
925 if T::upcast_key(old_key) != value.key() {
926 panic!(
927 "must insert a value with \
928 the same key used to create the entry"
929 );
930 }
931
932 // Now that we know the key is the same, we can replace the value
933 // directly without needing to tweak any tables.
934 self.items.replace(index, value)
935 }
936}
937
938impl<'a, T: IdOrdItem> fmt::Debug for IdOrdMap<T>
939where
940 T: fmt::Debug,
941 T::Key<'a>: fmt::Debug,
942 T: 'a,
943{
944 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
945 let mut map = f.debug_map();
946
947 for item in self.iter() {
948 let key = item.key();
949
950 // SAFETY:
951 //
952 // * Lifetime extension: for a type T and two lifetime params 'a and
953 // 'b, T<'a> and T<'b> aren't guaranteed to have the same layout,
954 // but (a) that is true today and (b) it would be shocking and
955 // break half the Rust ecosystem if that were to change in the
956 // future.
957 // * We only use key within the scope of this block before immediately
958 // dropping it. In particular, map.entry calls key.fmt() without
959 // holding a reference to it.
960 let key: T::Key<'a> =
961 unsafe { core::mem::transmute::<T::Key<'_>, T::Key<'a>>(key) };
962
963 map.entry(&key, &item);
964 }
965 map.finish()
966 }
967}
968
969impl<T: IdOrdItem + PartialEq> PartialEq for IdOrdMap<T> {
970 fn eq(&self, other: &Self) -> bool {
971 // Items are stored in sorted order, so we can just walk over both
972 // iterators.
973 if self.items.len() != other.items.len() {
974 return false;
975 }
976
977 self.iter().zip(other.iter()).all(|(item1, item2)| {
978 // Check that the items are equal.
979 item1 == item2
980 })
981 }
982}
983
984// The Eq bound on T ensures that the IdOrdMap forms an equivalence class.
985impl<T: IdOrdItem + Eq> Eq for IdOrdMap<T> {}
986
987/// The `Extend` implementation overwrites duplicates. In the future, there will
988/// also be an `extend_unique` method that will return an error.
989impl<T: IdOrdItem> Extend<T> for IdOrdMap<T> {
990 fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
991 for item in iter {
992 self.insert_overwrite(item);
993 }
994 }
995}
996
997impl<'a, T: IdOrdItem> IntoIterator for &'a IdOrdMap<T> {
998 type Item = &'a T;
999 type IntoIter = Iter<'a, T>;
1000
1001 #[inline]
1002 fn into_iter(self) -> Self::IntoIter {
1003 self.iter()
1004 }
1005}
1006
1007impl<'a, T: IdOrdItem> IntoIterator for &'a mut IdOrdMap<T>
1008where
1009 T::Key<'a>: Hash,
1010{
1011 type Item = RefMut<'a, T>;
1012 type IntoIter = IterMut<'a, T>;
1013
1014 #[inline]
1015 fn into_iter(self) -> Self::IntoIter {
1016 self.iter_mut()
1017 }
1018}
1019
1020impl<T: IdOrdItem> IntoIterator for IdOrdMap<T> {
1021 type Item = T;
1022 type IntoIter = IntoIter<T>;
1023
1024 #[inline]
1025 fn into_iter(self) -> Self::IntoIter {
1026 IntoIter::new(self.items, self.tables)
1027 }
1028}
1029
1030/// The `FromIterator` implementation for `IdOrdMap` overwrites duplicate
1031/// items.
1032///
1033/// To reject duplicates, use [`IdOrdMap::from_iter_unique`].
1034impl<T: IdOrdItem> FromIterator<T> for IdOrdMap<T> {
1035 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
1036 let mut map = IdOrdMap::new();
1037 for value in iter {
1038 map.insert_overwrite(value);
1039 }
1040 map
1041 }
1042}