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