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