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