slotmap/hop.rs
1//! Contains the faster iteration, slower insertion/removal slot map
2//! implementation.
3//!
4//! This data structure is essentially the same as a regular [`SlotMap`], but
5//! maintains extra information when inserting/removing elements that allows it
6//! to 'hop over' vacant slots during iteration, making it potentially much
7//! faster for iteration.
8//!
9//! The trade-off is that compared to a regular [`SlotMap`] insertion/removal is
10//! roughly twice as slow. Random indexing has identical performance for both.
11//!
12//! [`SlotMap`]: crate::SlotMap
13
14#![allow(deprecated)]
15
16use alloc::collections::TryReserveError;
17use alloc::vec::Vec;
18use core::fmt;
19use core::iter::FusedIterator;
20use core::marker::PhantomData;
21use core::mem::{ManuallyDrop, MaybeUninit};
22use core::ops::{Index, IndexMut};
23
24use crate::util::{Never, PanicOnDrop, UnwrapNever};
25use crate::{DefaultKey, Key, KeyData};
26
27// Metadata to maintain the freelist.
28#[derive(Clone, Copy, Debug)]
29struct FreeListEntry {
30 next: u32,
31 prev: u32,
32 other_end: u32,
33}
34
35// Storage inside a slot or metadata for the freelist when vacant.
36union SlotUnion<T> {
37 value: ManuallyDrop<T>,
38 free: FreeListEntry,
39}
40
41// A slot, which represents storage for a value and a current version.
42// Can be occupied or vacant.
43struct Slot<T> {
44 u: SlotUnion<T>,
45 version: u32, // Even = vacant, odd = occupied.
46}
47
48// Safe API to read a slot.
49enum SlotContent<'a, T: 'a> {
50 Occupied(&'a T),
51 Vacant(&'a FreeListEntry),
52}
53
54enum SlotContentMut<'a, T: 'a> {
55 OccupiedMut(&'a mut T),
56 VacantMut(&'a mut FreeListEntry),
57}
58
59use self::SlotContent::{Occupied, Vacant};
60use self::SlotContentMut::{OccupiedMut, VacantMut};
61
62impl<T> Slot<T> {
63 // Is this slot occupied?
64 #[inline(always)]
65 pub fn occupied(&self) -> bool {
66 self.version % 2 == 1
67 }
68
69 pub fn get(&self) -> SlotContent<'_, T> {
70 unsafe {
71 if self.occupied() {
72 Occupied(&*self.u.value)
73 } else {
74 Vacant(&self.u.free)
75 }
76 }
77 }
78
79 pub fn get_mut(&mut self) -> SlotContentMut<'_, T> {
80 unsafe {
81 if self.occupied() {
82 OccupiedMut(&mut *self.u.value)
83 } else {
84 VacantMut(&mut self.u.free)
85 }
86 }
87 }
88}
89
90impl<T> Drop for Slot<T> {
91 fn drop(&mut self) {
92 if core::mem::needs_drop::<T>() && self.occupied() {
93 // This is safe because we checked that we're occupied.
94 unsafe {
95 ManuallyDrop::drop(&mut self.u.value);
96 }
97 }
98 }
99}
100
101impl<T: Clone> Clone for Slot<T> {
102 fn clone(&self) -> Self {
103 Self {
104 u: match self.get() {
105 Occupied(value) => SlotUnion {
106 value: ManuallyDrop::new(value.clone()),
107 },
108 Vacant(&free) => SlotUnion { free },
109 },
110 version: self.version,
111 }
112 }
113
114 fn clone_from(&mut self, source: &Self) {
115 match (self.get_mut(), source.get()) {
116 (OccupiedMut(self_val), Occupied(source_val)) => self_val.clone_from(source_val),
117 (VacantMut(self_free), Vacant(&source_free)) => *self_free = source_free,
118 (OccupiedMut(_), Vacant(&free)) => unsafe {
119 // SAFETY: we are occupied.
120 ManuallyDrop::drop(&mut self.u.value);
121 self.u = SlotUnion { free };
122 },
123 (VacantMut(_), Occupied(value)) => {
124 self.u = SlotUnion {
125 value: ManuallyDrop::new(value.clone()),
126 }
127 },
128 }
129 self.version = source.version;
130 }
131}
132
133impl<T: fmt::Debug> fmt::Debug for Slot<T> {
134 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
135 let mut builder = fmt.debug_struct("Slot");
136 builder.field("version", &self.version);
137 match self.get() {
138 Occupied(value) => builder.field("value", value).finish(),
139 Vacant(free) => builder.field("free", free).finish(),
140 }
141 }
142}
143
144/// Hop slot map, storage with stable unique keys.
145///
146/// See [crate documentation](crate) for more details.
147#[deprecated(
148 since = "1.1.0",
149 note = "Use `SlotMap` or `DenseSlotMap` instead, the `HopSlotMap` is no longer maintained and will be removed in 2.0."
150)]
151#[derive(Debug)]
152pub struct HopSlotMap<K: Key, V> {
153 slots: Vec<Slot<V>>,
154 num_elems: u32,
155 _k: PhantomData<fn(K) -> K>,
156}
157
158impl<V> HopSlotMap<DefaultKey, V> {
159 /// Constructs a new, empty [`HopSlotMap`].
160 ///
161 /// # Examples
162 ///
163 /// ```
164 /// # use slotmap::*;
165 /// let mut sm: HopSlotMap<_, i32> = HopSlotMap::new();
166 /// ```
167 pub fn new() -> Self {
168 Self::with_capacity_and_key(0)
169 }
170
171 /// Creates an empty [`HopSlotMap`] with the given capacity.
172 ///
173 /// The slot map will not reallocate until it holds at least `capacity`
174 /// elements.
175 ///
176 /// # Examples
177 ///
178 /// ```
179 /// # use slotmap::*;
180 /// let mut sm: HopSlotMap<_, i32> = HopSlotMap::with_capacity(10);
181 /// ```
182 pub fn with_capacity(capacity: usize) -> Self {
183 Self::with_capacity_and_key(capacity)
184 }
185}
186
187impl<K: Key, V> HopSlotMap<K, V> {
188 /// Constructs a new, empty [`HopSlotMap`] with a custom key type.
189 ///
190 /// # Examples
191 ///
192 /// ```
193 /// # use slotmap::*;
194 /// new_key_type! {
195 /// struct PositionKey;
196 /// }
197 /// let mut positions: HopSlotMap<PositionKey, i32> = HopSlotMap::with_key();
198 /// ```
199 pub fn with_key() -> Self {
200 Self::with_capacity_and_key(0)
201 }
202
203 /// Creates an empty [`HopSlotMap`] with the given capacity and a custom key
204 /// type.
205 ///
206 /// The slot map will not reallocate until it holds at least `capacity`
207 /// elements.
208 ///
209 /// # Examples
210 ///
211 /// ```
212 /// # use slotmap::*;
213 /// new_key_type! {
214 /// struct MessageKey;
215 /// }
216 /// let mut messages = HopSlotMap::with_capacity_and_key(3);
217 /// let welcome: MessageKey = messages.insert("Welcome");
218 /// let good_day = messages.insert("Good day");
219 /// let hello = messages.insert("Hello");
220 /// ```
221 pub fn with_capacity_and_key(capacity: usize) -> Self {
222 // Create slots with sentinel at index 0.
223 let mut slots = Vec::with_capacity(capacity + 1);
224 slots.push(Slot {
225 u: SlotUnion {
226 free: FreeListEntry {
227 next: 0,
228 prev: 0,
229 other_end: 0,
230 },
231 },
232 version: 0,
233 });
234
235 Self {
236 slots,
237 num_elems: 0,
238 _k: PhantomData,
239 }
240 }
241
242 /// Returns the number of elements in the slot map.
243 ///
244 /// # Examples
245 ///
246 /// ```
247 /// # use slotmap::*;
248 /// let mut sm = HopSlotMap::with_capacity(10);
249 /// sm.insert("len() counts actual elements, not capacity");
250 /// let key = sm.insert("removed elements don't count either");
251 /// sm.remove(key);
252 /// assert_eq!(sm.len(), 1);
253 /// ```
254 pub fn len(&self) -> usize {
255 self.num_elems as usize
256 }
257
258 /// Returns if the slot map is empty.
259 ///
260 /// # Examples
261 ///
262 /// ```
263 /// # use slotmap::*;
264 /// let mut sm = HopSlotMap::new();
265 /// let key = sm.insert("dummy");
266 /// assert_eq!(sm.is_empty(), false);
267 /// sm.remove(key);
268 /// assert_eq!(sm.is_empty(), true);
269 /// ```
270 pub fn is_empty(&self) -> bool {
271 self.num_elems == 0
272 }
273
274 /// Returns the number of elements the [`HopSlotMap`] can hold without
275 /// reallocating.
276 ///
277 /// # Examples
278 ///
279 /// ```
280 /// # use slotmap::*;
281 /// let sm: HopSlotMap<_, f64> = HopSlotMap::with_capacity(10);
282 /// assert_eq!(sm.capacity(), 10);
283 /// ```
284 pub fn capacity(&self) -> usize {
285 // One slot is reserved for the freelist sentinel.
286 self.slots.capacity() - 1
287 }
288
289 /// Reserves capacity for at least `additional` more elements to be inserted
290 /// in the [`HopSlotMap`]. The collection may reserve more space to
291 /// avoid frequent reallocations.
292 ///
293 /// # Panics
294 ///
295 /// Panics if the new allocation size overflows [`usize`].
296 ///
297 /// # Examples
298 ///
299 /// ```
300 /// # use slotmap::*;
301 /// let mut sm = HopSlotMap::new();
302 /// sm.insert("foo");
303 /// sm.reserve(32);
304 /// assert!(sm.capacity() >= 33);
305 /// ```
306 pub fn reserve(&mut self, additional: usize) {
307 // One slot is reserved for the freelist sentinel.
308 let needed = (self.len() + additional).saturating_sub(self.slots.len() - 1);
309 self.slots.reserve(needed);
310 }
311
312 /// Tries to reserve capacity for at least `additional` more elements to be
313 /// inserted in the [`HopSlotMap`]. The collection may reserve more space to
314 /// avoid frequent reallocations.
315 ///
316 /// # Examples
317 ///
318 /// ```
319 /// # use slotmap::*;
320 /// let mut sm = HopSlotMap::new();
321 /// sm.insert("foo");
322 /// sm.try_reserve(32).unwrap();
323 /// assert!(sm.capacity() >= 33);
324 /// ```
325 pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
326 // One slot is reserved for the freelist sentinel.
327 let needed = (self.len() + additional).saturating_sub(self.slots.len() - 1);
328 self.slots.try_reserve(needed)
329 }
330
331 /// Returns [`true`] if the slot map contains `key`.
332 ///
333 /// # Examples
334 ///
335 /// ```
336 /// # use slotmap::*;
337 /// let mut sm = HopSlotMap::new();
338 /// let key = sm.insert(42);
339 /// assert_eq!(sm.contains_key(key), true);
340 /// sm.remove(key);
341 /// assert_eq!(sm.contains_key(key), false);
342 /// ```
343 pub fn contains_key(&self, key: K) -> bool {
344 let kd = key.data();
345 self.slots
346 .get(kd.idx as usize)
347 .map_or(false, |slot| slot.version == kd.version.get())
348 }
349
350 /// Inserts a value into the slot map. Returns a unique key that can be
351 /// used to access this value.
352 ///
353 /// # Panics
354 ///
355 /// Panics if the number of elements in the slot map equals
356 /// 2<sup>32</sup> - 2.
357 ///
358 /// # Examples
359 ///
360 /// ```
361 /// # use slotmap::*;
362 /// let mut sm = HopSlotMap::new();
363 /// let key = sm.insert(42);
364 /// assert_eq!(sm[key], 42);
365 /// ```
366 #[inline(always)]
367 pub fn insert(&mut self, value: V) -> K {
368 self.try_insert_with_key::<_, Never>(move |_| Ok(value))
369 .unwrap_never()
370 }
371
372 // Helper function to make using the freelist painless.
373 // For that same ergonomy it uses u32, not usize as index.
374 // Safe iff idx is a valid index and the slot at that index is vacant.
375 unsafe fn freelist(&mut self, idx: u32) -> &mut FreeListEntry {
376 &mut self.slots.get_unchecked_mut(idx as usize).u.free
377 }
378
379 /// Inserts a value given by `f` into the slot map. The key where the
380 /// value will be stored is passed into `f`. This is useful to store values
381 /// that contain their own key.
382 ///
383 /// # Panics
384 ///
385 /// Panics if the number of elements in the slot map equals
386 /// 2<sup>32</sup> - 2.
387 ///
388 /// # Examples
389 ///
390 /// ```
391 /// # use slotmap::*;
392 /// let mut sm = HopSlotMap::new();
393 /// let key = sm.insert_with_key(|k| (k, 20));
394 /// assert_eq!(sm[key], (key, 20));
395 /// ```
396 #[inline(always)]
397 pub fn insert_with_key<F>(&mut self, f: F) -> K
398 where
399 F: FnOnce(K) -> V,
400 {
401 self.try_insert_with_key::<_, Never>(move |k| Ok(f(k)))
402 .unwrap_never()
403 }
404
405 /// Inserts a value given by `f` into the slot map. The key where the
406 /// value will be stored is passed into `f`. This is useful to store values
407 /// that contain their own key.
408 ///
409 /// If `f` returns `Err`, this method returns the error. The slotmap is untouched.
410 ///
411 /// # Panics
412 ///
413 /// Panics if the number of elements in the slot map equals
414 /// 2<sup>32</sup> - 2.
415 ///
416 /// # Examples
417 ///
418 /// ```
419 /// # use slotmap::*;
420 /// let mut sm = HopSlotMap::new();
421 /// let key = sm.try_insert_with_key::<_, ()>(|k| Ok((k, 20))).unwrap();
422 /// assert_eq!(sm[key], (key, 20));
423 ///
424 /// sm.try_insert_with_key::<_, ()>(|k| Err(())).unwrap_err();
425 /// ```
426 pub fn try_insert_with_key<F, E>(&mut self, f: F) -> Result<K, E>
427 where
428 F: FnOnce(K) -> Result<V, E>,
429 {
430 // In case f panics, we don't make any changes until we have the value.
431 let new_num_elems = self.num_elems + 1;
432 if new_num_elems == u32::MAX {
433 panic!("HopSlotMap number of elements overflow");
434 }
435
436 // All unsafe accesses here are safe due to the invariants of the slot
437 // map freelist.
438 unsafe {
439 let head = self.freelist(0).next;
440
441 // We have a contiguous block of vacant slots starting at head.
442 // Put our new element at the back slot.
443 let front = head;
444 let back = self.freelist(front).other_end;
445 let slot_idx = back as usize;
446
447 // Freelist is empty.
448 if slot_idx == 0 {
449 let version = 1;
450 let key = KeyData::new(self.slots.len() as u32, version).into();
451
452 self.slots.push(Slot {
453 u: SlotUnion {
454 value: ManuallyDrop::new(f(key)?),
455 },
456 version,
457 });
458 self.num_elems = new_num_elems;
459 return Ok(key);
460 }
461
462 // Compute value first in case f panics or returns an error.
463 let occupied_version = self.slots[slot_idx].version | 1;
464 let key = KeyData::new(slot_idx as u32, occupied_version).into();
465 let value = f(key)?;
466
467 // Update freelist.
468 if front == back {
469 // Used last slot in this block, move next one to head.
470 let new_head = self.freelist(front).next;
471 self.freelist(0).next = new_head;
472 self.freelist(new_head).prev = 0;
473 } else {
474 // Continue using this block, only need to update other_ends.
475 let new_back = back - 1;
476 self.freelist(new_back).other_end = front;
477 self.freelist(front).other_end = new_back;
478 }
479
480 // And finally insert the value.
481 let slot = &mut self.slots[slot_idx];
482 slot.version = occupied_version;
483 slot.u.value = ManuallyDrop::new(value);
484 self.num_elems = new_num_elems;
485 Ok(key)
486 }
487 }
488
489 // Helper function to remove a value from a slot. Safe iff the slot is
490 // occupied. Returns the value removed.
491 #[inline(always)]
492 unsafe fn remove_from_slot(&mut self, idx: usize) -> V {
493 // Remove value from slot.
494 let slot = self.slots.get_unchecked_mut(idx);
495 slot.version = slot.version.wrapping_add(1);
496 let value = ManuallyDrop::take(&mut slot.u.value);
497
498 // This is safe and can't underflow because of the sentinel element at
499 // the start.
500 let left_vacant = !self.slots.get_unchecked(idx - 1).occupied();
501 let right_vacant = self.slots.get(idx + 1).map_or(false, |s| !s.occupied());
502
503 // Maintain freelist by either appending/prepending this slot to a
504 // contiguous block to the left or right, merging the two blocks to the
505 // left and right or inserting a new block.
506 let i = idx as u32;
507 match (left_vacant, right_vacant) {
508 (false, false) => {
509 // New block, insert it at the tail.
510 let old_tail = self.freelist(0).prev;
511 self.freelist(0).prev = i;
512 self.freelist(old_tail).next = i;
513 *self.freelist(i) = FreeListEntry {
514 other_end: i,
515 next: 0,
516 prev: old_tail,
517 };
518 },
519
520 (false, true) => {
521 // Prepend to vacant block on right.
522 let front_data = *self.freelist(i + 1);
523
524 // Since the start of this block moved we must update the pointers to it.
525 self.freelist(front_data.other_end).other_end = i;
526 self.freelist(front_data.prev).next = i;
527 self.freelist(front_data.next).prev = i;
528 *self.freelist(i) = front_data;
529 },
530
531 (true, false) => {
532 // Append to vacant block on left.
533 let front = self.freelist(i - 1).other_end;
534 self.freelist(i).other_end = front;
535 self.freelist(front).other_end = i;
536 },
537
538 (true, true) => {
539 // We must merge left and right.
540 // First snip right out of the freelist.
541 let right = *self.freelist(i + 1);
542 self.freelist(right.prev).next = right.next;
543 self.freelist(right.next).prev = right.prev;
544
545 // Now update endpoints.
546 let front = self.freelist(i - 1).other_end;
547 let back = right.other_end;
548 self.freelist(front).other_end = back;
549 self.freelist(back).other_end = front;
550 },
551 }
552
553 self.num_elems -= 1;
554
555 value
556 }
557
558 /// Removes a key from the slot map, returning the value at the key if the
559 /// key was not previously removed.
560 ///
561 /// # Examples
562 ///
563 /// ```
564 /// # use slotmap::*;
565 /// let mut sm = HopSlotMap::new();
566 /// let key = sm.insert(42);
567 /// assert_eq!(sm.remove(key), Some(42));
568 /// assert_eq!(sm.remove(key), None);
569 /// ```
570 pub fn remove(&mut self, key: K) -> Option<V> {
571 let kd = key.data();
572 if self.contains_key(key) {
573 // This is safe because we know that the slot is occupied.
574 Some(unsafe { self.remove_from_slot(kd.idx as usize) })
575 } else {
576 None
577 }
578 }
579
580 /// Retains only the elements specified by the predicate.
581 ///
582 /// In other words, remove all key-value pairs `(k, v)` such that
583 /// `f(k, &mut v)` returns false. This method invalidates any removed keys.
584 ///
585 /// # Examples
586 ///
587 /// ```
588 /// # use slotmap::*;
589 /// let mut sm = HopSlotMap::new();
590 ///
591 /// let k1 = sm.insert(0);
592 /// let k2 = sm.insert(1);
593 /// let k3 = sm.insert(2);
594 ///
595 /// sm.retain(|key, val| key == k1 || *val == 1);
596 ///
597 /// assert!(sm.contains_key(k1));
598 /// assert!(sm.contains_key(k2));
599 /// assert!(!sm.contains_key(k3));
600 ///
601 /// assert_eq!(2, sm.len());
602 /// ```
603 pub fn retain<F>(&mut self, mut f: F)
604 where
605 F: FnMut(K, &mut V) -> bool,
606 {
607 let mut elems_left_to_scan = self.len();
608 let mut cur = unsafe { self.slots.get_unchecked(0).u.free.other_end as usize + 1 };
609 while elems_left_to_scan > 0 {
610 // This is safe because removing elements does not shrink slots, cur always
611 // points to an occupied slot.
612 let idx = cur;
613 let slot = unsafe { self.slots.get_unchecked_mut(cur) };
614 let version = slot.version;
615 let key = KeyData::new(cur as u32, version).into();
616 let should_remove = !f(key, unsafe { &mut *slot.u.value });
617
618 cur = match self.slots.get(cur + 1).map(|s| s.get()) {
619 Some(Occupied(_)) => cur + 1,
620 Some(Vacant(free)) => free.other_end as usize + 1,
621 None => 0,
622 };
623
624 if should_remove {
625 // This must happen after getting the next index.
626 unsafe { self.remove_from_slot(idx) };
627 }
628
629 elems_left_to_scan -= 1;
630 }
631 }
632
633 /// Clears the slot map. Keeps the allocated memory for reuse.
634 ///
635 /// # Examples
636 ///
637 /// ```
638 /// # use slotmap::*;
639 /// let mut sm = HopSlotMap::new();
640 /// for i in 0..10 {
641 /// sm.insert(i);
642 /// }
643 /// assert_eq!(sm.len(), 10);
644 /// sm.clear();
645 /// assert_eq!(sm.len(), 0);
646 /// ```
647 pub fn clear(&mut self) {
648 self.drain();
649 }
650
651 /// Clears the slot map, returning all key-value pairs in an arbitrary order
652 /// as an iterator. Keeps the allocated memory for reuse.
653 ///
654 /// When the iterator is dropped all elements in the slot map are removed,
655 /// even if the iterator was not fully consumed. If the iterator is not
656 /// dropped (using e.g. [`std::mem::forget`]), only the elements that were
657 /// iterated over are removed.
658 ///
659 /// # Examples
660 ///
661 /// ```
662 /// # use slotmap::*;
663 /// let mut sm = HopSlotMap::new();
664 /// let k = sm.insert(0);
665 /// let v: Vec<_> = sm.drain().collect();
666 /// assert_eq!(sm.len(), 0);
667 /// assert_eq!(v, vec![(k, 0)]);
668 /// ```
669 pub fn drain(&mut self) -> Drain<'_, K, V> {
670 Drain {
671 cur: unsafe { self.slots.get_unchecked(0).u.free.other_end as usize + 1 },
672 sm: self,
673 }
674 }
675
676 /// Returns a reference to the value corresponding to the key.
677 ///
678 /// # Examples
679 ///
680 /// ```
681 /// # use slotmap::*;
682 /// let mut sm = HopSlotMap::new();
683 /// let key = sm.insert("bar");
684 /// assert_eq!(sm.get(key), Some(&"bar"));
685 /// sm.remove(key);
686 /// assert_eq!(sm.get(key), None);
687 /// ```
688 pub fn get(&self, key: K) -> Option<&V> {
689 let kd = key.data();
690 // This is safe because we check version first and a key always contains
691 // an odd version, thus we are occupied.
692 self.slots
693 .get(kd.idx as usize)
694 .filter(|slot| slot.version == kd.version.get())
695 .map(|slot| unsafe { &*slot.u.value })
696 }
697
698 /// Returns a reference to the value corresponding to the key without
699 /// version or bounds checking.
700 ///
701 /// # Safety
702 ///
703 /// This should only be used if `contains_key(key)` is true. Otherwise it is
704 /// dangerous undefined behavior.
705 ///
706 /// # Examples
707 ///
708 /// ```
709 /// # use slotmap::*;
710 /// let mut sm = HopSlotMap::new();
711 /// let key = sm.insert("bar");
712 /// assert_eq!(unsafe { sm.get_unchecked(key) }, &"bar");
713 /// sm.remove(key);
714 /// // sm.get_unchecked(key) is now dangerous!
715 /// ```
716 pub unsafe fn get_unchecked(&self, key: K) -> &V {
717 debug_assert!(self.contains_key(key));
718 &self.slots.get_unchecked(key.data().idx as usize).u.value
719 }
720
721 /// Returns a mutable reference to the value corresponding to the key.
722 ///
723 /// # Examples
724 ///
725 /// ```
726 /// # use slotmap::*;
727 /// let mut sm = HopSlotMap::new();
728 /// let key = sm.insert(3.5);
729 /// if let Some(x) = sm.get_mut(key) {
730 /// *x += 3.0;
731 /// }
732 /// assert_eq!(sm[key], 6.5);
733 /// ```
734 pub fn get_mut(&mut self, key: K) -> Option<&mut V> {
735 let kd = key.data();
736 // This is safe because we check version first and a key always contains
737 // an odd version, thus we are occupied.
738 self.slots
739 .get_mut(kd.idx as usize)
740 .filter(|slot| slot.version == kd.version.get())
741 .map(|slot| unsafe { &mut *slot.u.value })
742 }
743
744 /// Returns a mutable reference to the value corresponding to the key
745 /// without version or bounds checking.
746 ///
747 /// # Safety
748 ///
749 /// This should only be used if `contains_key(key)` is true. Otherwise it is
750 /// dangerous undefined behavior.
751 ///
752 /// # Examples
753 ///
754 /// ```
755 /// # use slotmap::*;
756 /// let mut sm = HopSlotMap::new();
757 /// let key = sm.insert("foo");
758 /// unsafe { *sm.get_unchecked_mut(key) = "bar" };
759 /// assert_eq!(sm[key], "bar");
760 /// sm.remove(key);
761 /// // sm.get_unchecked_mut(key) is now dangerous!
762 /// ```
763 pub unsafe fn get_unchecked_mut(&mut self, key: K) -> &mut V {
764 debug_assert!(self.contains_key(key));
765 &mut self
766 .slots
767 .get_unchecked_mut(key.data().idx as usize)
768 .u
769 .value
770 }
771
772 /// Returns mutable references to the values corresponding to the given
773 /// keys. All keys must be valid and disjoint, otherwise [`None`] is
774 /// returned.
775 ///
776 /// Requires at least stable Rust version 1.51.
777 ///
778 /// # Examples
779 ///
780 /// ```
781 /// # use slotmap::*;
782 /// let mut sm = HopSlotMap::new();
783 /// let ka = sm.insert("butter");
784 /// let kb = sm.insert("apples");
785 /// let kc = sm.insert("charlie");
786 /// sm.remove(kc); // Make key c invalid.
787 /// assert_eq!(sm.get_disjoint_mut([ka, kb, kc]), None); // Has invalid key.
788 /// assert_eq!(sm.get_disjoint_mut([ka, ka]), None); // Not disjoint.
789 /// let [a, b] = sm.get_disjoint_mut([ka, kb]).unwrap();
790 /// std::mem::swap(a, b);
791 /// assert_eq!(sm[ka], "apples");
792 /// assert_eq!(sm[kb], "butter");
793 /// ```
794 pub fn get_disjoint_mut<const N: usize>(&mut self, keys: [K; N]) -> Option<[&mut V; N]> {
795 let mut ptrs: [MaybeUninit<*mut V>; N] = [(); N].map(|_| MaybeUninit::uninit());
796 let slots_ptr = self.slots.as_mut_ptr();
797
798 let mut i = 0;
799 while i < N {
800 let kd = keys[i].data();
801 if !self.contains_key(kd.into()) {
802 break;
803 }
804
805 // This key is valid, and thus the slot is occupied. Temporarily
806 // mark it as unoccupied so duplicate keys would show up as invalid.
807 // This gives us a linear time disjointness check.
808 unsafe {
809 let slot = &mut *slots_ptr.add(kd.idx as usize);
810 slot.version ^= 1;
811 ptrs[i] = MaybeUninit::new(&mut *slot.u.value);
812 }
813 i += 1;
814 }
815
816 // Undo temporary unoccupied markings.
817 for k in &keys[..i] {
818 let idx = k.data().idx as usize;
819 unsafe {
820 (*slots_ptr.add(idx)).version ^= 1;
821 }
822 }
823
824 if i == N {
825 // All were valid and disjoint.
826 Some(ptrs.map(|p| unsafe { &mut *p.assume_init() }))
827 } else {
828 None
829 }
830 }
831
832 /// Returns mutable references to the values corresponding to the given
833 /// keys. All keys must be valid and disjoint.
834 ///
835 /// Requires at least stable Rust version 1.51.
836 ///
837 /// # Safety
838 ///
839 /// This should only be used if `contains_key(key)` is true for every given
840 /// key and no two keys are equal. Otherwise it is potentially unsafe.
841 ///
842 /// # Examples
843 ///
844 /// ```
845 /// # use slotmap::*;
846 /// let mut sm = HopSlotMap::new();
847 /// let ka = sm.insert("butter");
848 /// let kb = sm.insert("apples");
849 /// let [a, b] = unsafe { sm.get_disjoint_unchecked_mut([ka, kb]) };
850 /// std::mem::swap(a, b);
851 /// assert_eq!(sm[ka], "apples");
852 /// assert_eq!(sm[kb], "butter");
853 /// ```
854 pub unsafe fn get_disjoint_unchecked_mut<const N: usize>(
855 &mut self,
856 keys: [K; N],
857 ) -> [&mut V; N] {
858 let slots_ptr = self.slots.as_mut_ptr();
859 keys.map(|k| unsafe {
860 let slot = &mut *slots_ptr.add(k.data().idx as usize);
861 &mut *slot.u.value
862 })
863 }
864
865 /// An iterator visiting all key-value pairs in an arbitrary order. The
866 /// iterator element type is `(K, &'a V)`.
867 ///
868 /// # Examples
869 ///
870 /// ```
871 /// # use slotmap::*;
872 /// let mut sm = HopSlotMap::new();
873 /// let k0 = sm.insert(0);
874 /// let k1 = sm.insert(1);
875 /// let k2 = sm.insert(2);
876 ///
877 /// for (k, v) in sm.iter() {
878 /// println!("key: {:?}, val: {}", k, v);
879 /// }
880 /// ```
881 pub fn iter(&self) -> Iter<'_, K, V> {
882 Iter {
883 cur: unsafe { self.slots.get_unchecked(0).u.free.other_end as usize + 1 },
884 num_left: self.len(),
885 slots: &self.slots[..],
886 _k: PhantomData,
887 }
888 }
889
890 /// An iterator visiting all key-value pairs in an arbitrary order, with
891 /// mutable references to the values. The iterator element type is
892 /// `(K, &'a mut V)`.
893 ///
894 /// # Examples
895 ///
896 /// ```
897 /// # use slotmap::*;
898 /// let mut sm = HopSlotMap::new();
899 /// let k0 = sm.insert(10);
900 /// let k1 = sm.insert(20);
901 /// let k2 = sm.insert(30);
902 ///
903 /// for (k, v) in sm.iter_mut() {
904 /// if k != k1 {
905 /// *v *= -1;
906 /// }
907 /// }
908 ///
909 /// assert_eq!(sm[k0], -10);
910 /// assert_eq!(sm[k1], 20);
911 /// assert_eq!(sm[k2], -30);
912 /// ```
913 pub fn iter_mut(&mut self) -> IterMut<'_, K, V> {
914 IterMut {
915 cur: 0,
916 num_left: self.len(),
917 slots: &mut self.slots[..],
918 _k: PhantomData,
919 }
920 }
921
922 /// An iterator visiting all keys in an arbitrary order. The iterator
923 /// element type is `K`.
924 ///
925 /// # Examples
926 ///
927 /// ```
928 /// # use slotmap::*;
929 /// # use std::collections::HashSet;
930 /// let mut sm = HopSlotMap::new();
931 /// let k0 = sm.insert(10);
932 /// let k1 = sm.insert(20);
933 /// let k2 = sm.insert(30);
934 /// let keys: HashSet<_> = sm.keys().collect();
935 /// let check: HashSet<_> = vec![k0, k1, k2].into_iter().collect();
936 /// assert_eq!(keys, check);
937 /// ```
938 pub fn keys(&self) -> Keys<'_, K, V> {
939 Keys { inner: self.iter() }
940 }
941
942 /// An iterator visiting all values in an arbitrary order. The iterator
943 /// element type is `&'a V`.
944 ///
945 /// # Examples
946 ///
947 /// ```
948 /// # use slotmap::*;
949 /// # use std::collections::HashSet;
950 /// let mut sm = HopSlotMap::new();
951 /// let k0 = sm.insert(10);
952 /// let k1 = sm.insert(20);
953 /// let k2 = sm.insert(30);
954 /// let values: HashSet<_> = sm.values().collect();
955 /// let check: HashSet<_> = vec![&10, &20, &30].into_iter().collect();
956 /// assert_eq!(values, check);
957 /// ```
958 pub fn values(&self) -> Values<'_, K, V> {
959 Values { inner: self.iter() }
960 }
961
962 /// An iterator visiting all values mutably in an arbitrary order. The
963 /// iterator element type is `&'a mut V`.
964 ///
965 /// # Examples
966 ///
967 /// ```
968 /// # use slotmap::*;
969 /// # use std::collections::HashSet;
970 /// let mut sm = HopSlotMap::new();
971 /// sm.insert(1);
972 /// sm.insert(2);
973 /// sm.insert(3);
974 /// sm.values_mut().for_each(|n| { *n *= 3 });
975 /// let values: HashSet<_> = sm.into_iter().map(|(_k, v)| v).collect();
976 /// let check: HashSet<_> = vec![3, 6, 9].into_iter().collect();
977 /// assert_eq!(values, check);
978 /// ```
979 pub fn values_mut(&mut self) -> ValuesMut<'_, K, V> {
980 ValuesMut {
981 inner: self.iter_mut(),
982 }
983 }
984}
985
986impl<K: Key, V> Clone for HopSlotMap<K, V>
987where
988 V: Clone,
989{
990 fn clone(&self) -> Self {
991 Self {
992 slots: self.slots.clone(),
993 ..*self
994 }
995 }
996
997 fn clone_from(&mut self, source: &Self) {
998 // There is no way to recover from a botched clone of slots due to a
999 // panic. So we abort by double-panicking.
1000 let guard = PanicOnDrop("abort - a panic during SlotMap::clone_from is unrecoverable");
1001 self.slots.clone_from(&source.slots);
1002 self.num_elems = source.num_elems;
1003 core::mem::forget(guard);
1004 }
1005}
1006
1007impl<K: Key, V> Default for HopSlotMap<K, V> {
1008 fn default() -> Self {
1009 Self::with_key()
1010 }
1011}
1012
1013impl<K: Key, V> Index<K> for HopSlotMap<K, V> {
1014 type Output = V;
1015
1016 fn index(&self, key: K) -> &V {
1017 match self.get(key) {
1018 Some(r) => r,
1019 None => panic!("invalid HopSlotMap key used"),
1020 }
1021 }
1022}
1023
1024impl<K: Key, V> IndexMut<K> for HopSlotMap<K, V> {
1025 fn index_mut(&mut self, key: K) -> &mut V {
1026 match self.get_mut(key) {
1027 Some(r) => r,
1028 None => panic!("invalid HopSlotMap key used"),
1029 }
1030 }
1031}
1032
1033// Iterators.
1034/// A draining iterator for [`HopSlotMap`].
1035///
1036/// This iterator is created by [`HopSlotMap::drain`].
1037#[derive(Debug)]
1038pub struct Drain<'a, K: Key + 'a, V: 'a> {
1039 cur: usize,
1040 sm: &'a mut HopSlotMap<K, V>,
1041}
1042
1043/// An iterator that moves key-value pairs out of a [`HopSlotMap`].
1044///
1045/// This iterator is created by calling the `into_iter` method on [`HopSlotMap`],
1046/// provided by the [`IntoIterator`] trait.
1047#[derive(Debug, Clone)]
1048pub struct IntoIter<K: Key, V> {
1049 cur: usize,
1050 num_left: usize,
1051 slots: Vec<Slot<V>>,
1052 _k: PhantomData<fn(K) -> K>,
1053}
1054
1055/// An iterator over the key-value pairs in a [`HopSlotMap`].
1056///
1057/// This iterator is created by [`HopSlotMap::iter`].
1058#[derive(Debug)]
1059pub struct Iter<'a, K: Key + 'a, V: 'a> {
1060 cur: usize,
1061 num_left: usize,
1062 slots: &'a [Slot<V>],
1063 _k: PhantomData<fn(K) -> K>,
1064}
1065
1066impl<'a, K: 'a + Key, V: 'a> Clone for Iter<'a, K, V> {
1067 fn clone(&self) -> Self {
1068 Iter {
1069 cur: self.cur,
1070 num_left: self.num_left,
1071 slots: self.slots,
1072 _k: self._k,
1073 }
1074 }
1075}
1076
1077/// A mutable iterator over the key-value pairs in a [`HopSlotMap`].
1078///
1079/// This iterator is created by [`HopSlotMap::iter_mut`].
1080#[derive(Debug)]
1081pub struct IterMut<'a, K: Key + 'a, V: 'a> {
1082 cur: usize,
1083 num_left: usize,
1084 slots: &'a mut [Slot<V>],
1085 _k: PhantomData<fn(K) -> K>,
1086}
1087
1088/// An iterator over the keys in a [`HopSlotMap`].
1089///
1090/// This iterator is created by [`HopSlotMap::keys`].
1091#[derive(Debug)]
1092pub struct Keys<'a, K: Key + 'a, V: 'a> {
1093 inner: Iter<'a, K, V>,
1094}
1095
1096impl<'a, K: 'a + Key, V: 'a> Clone for Keys<'a, K, V> {
1097 fn clone(&self) -> Self {
1098 Keys {
1099 inner: self.inner.clone(),
1100 }
1101 }
1102}
1103
1104/// An iterator over the values in a [`HopSlotMap`].
1105///
1106/// This iterator is created by [`HopSlotMap::values`].
1107#[derive(Debug)]
1108pub struct Values<'a, K: Key + 'a, V: 'a> {
1109 inner: Iter<'a, K, V>,
1110}
1111
1112impl<'a, K: 'a + Key, V: 'a> Clone for Values<'a, K, V> {
1113 fn clone(&self) -> Self {
1114 Values {
1115 inner: self.inner.clone(),
1116 }
1117 }
1118}
1119
1120/// A mutable iterator over the values in a [`HopSlotMap`].
1121///
1122/// This iterator is created by [`HopSlotMap::values_mut`].
1123#[derive(Debug)]
1124pub struct ValuesMut<'a, K: Key + 'a, V: 'a> {
1125 inner: IterMut<'a, K, V>,
1126}
1127
1128impl<'a, K: Key, V> Iterator for Drain<'a, K, V> {
1129 type Item = (K, V);
1130
1131 fn next(&mut self) -> Option<(K, V)> {
1132 // All unchecked indices are safe due to the invariants of the freelist
1133 // and that self.sm.len() guarantees there is another element.
1134 if self.sm.is_empty() {
1135 return None;
1136 }
1137
1138 // Skip ahead to next element. Must do this before removing.
1139 let idx = self.cur;
1140 self.cur = match self.sm.slots.get(idx + 1).map(|s| s.get()) {
1141 Some(Occupied(_)) => idx + 1,
1142 Some(Vacant(free)) => free.other_end as usize + 1,
1143 None => 0,
1144 };
1145
1146 let key = KeyData::new(idx as u32, unsafe {
1147 self.sm.slots.get_unchecked(idx).version
1148 });
1149 Some((key.into(), unsafe { self.sm.remove_from_slot(idx) }))
1150 }
1151
1152 fn size_hint(&self) -> (usize, Option<usize>) {
1153 (self.sm.len(), Some(self.sm.len()))
1154 }
1155}
1156
1157impl<'a, K: Key, V> Drop for Drain<'a, K, V> {
1158 fn drop(&mut self) {
1159 self.for_each(|_drop| {});
1160 }
1161}
1162
1163impl<K: Key, V> Iterator for IntoIter<K, V> {
1164 type Item = (K, V);
1165
1166 fn next(&mut self) -> Option<(K, V)> {
1167 if self.cur >= self.slots.len() {
1168 return None;
1169 }
1170
1171 let idx = match self.slots[self.cur].get() {
1172 Occupied(_) => self.cur,
1173 Vacant(free) => {
1174 // Skip block of contiguous vacant slots.
1175 let idx = free.other_end as usize + 1;
1176 if idx >= self.slots.len() {
1177 return None;
1178 }
1179 idx
1180 },
1181 };
1182
1183 self.cur = idx + 1;
1184 self.num_left -= 1;
1185 let slot = &mut self.slots[idx];
1186 let key = KeyData::new(idx as u32, slot.version).into();
1187 slot.version = 0; // Prevent dropping after extracting the value.
1188 Some((key, unsafe { ManuallyDrop::take(&mut slot.u.value) }))
1189 }
1190
1191 fn size_hint(&self) -> (usize, Option<usize>) {
1192 (self.num_left, Some(self.num_left))
1193 }
1194}
1195
1196impl<'a, K: Key, V> Iterator for Iter<'a, K, V> {
1197 type Item = (K, &'a V);
1198
1199 fn next(&mut self) -> Option<(K, &'a V)> {
1200 // All unchecked indices are safe due to the invariants of the freelist
1201 // and that num_left guarantees there is another element.
1202 if self.num_left == 0 {
1203 return None;
1204 }
1205 self.num_left -= 1;
1206
1207 let idx = match unsafe { self.slots.get_unchecked(self.cur).get() } {
1208 Occupied(_) => self.cur,
1209 Vacant(free) => free.other_end as usize + 1,
1210 };
1211
1212 self.cur = idx + 1;
1213 let slot = unsafe { self.slots.get_unchecked(idx) };
1214 let key = KeyData::new(idx as u32, slot.version).into();
1215 Some((key, unsafe { &*slot.u.value }))
1216 }
1217
1218 fn size_hint(&self) -> (usize, Option<usize>) {
1219 (self.num_left, Some(self.num_left))
1220 }
1221}
1222
1223impl<'a, K: Key, V> Iterator for IterMut<'a, K, V> {
1224 type Item = (K, &'a mut V);
1225
1226 fn next(&mut self) -> Option<(K, &'a mut V)> {
1227 if self.cur >= self.slots.len() {
1228 return None;
1229 }
1230
1231 let idx = match self.slots[self.cur].get() {
1232 Occupied(_) => self.cur,
1233 Vacant(free) => {
1234 // Skip block of contiguous vacant slots.
1235 let idx = free.other_end as usize + 1;
1236 if idx >= self.slots.len() {
1237 return None;
1238 }
1239 idx
1240 },
1241 };
1242
1243 self.cur = idx + 1;
1244 self.num_left -= 1;
1245
1246 // Unsafe necessary because Rust can't deduce that we won't
1247 // return multiple references to the same value.
1248 let slot = &mut self.slots[idx];
1249 let version = slot.version;
1250 let value_ref = unsafe {
1251 let ptr: *mut V = &mut *slot.u.value;
1252 &mut *ptr
1253 };
1254 Some((KeyData::new(idx as u32, version).into(), value_ref))
1255 }
1256
1257 fn size_hint(&self) -> (usize, Option<usize>) {
1258 (self.num_left, Some(self.num_left))
1259 }
1260}
1261
1262impl<'a, K: Key, V> Iterator for Keys<'a, K, V> {
1263 type Item = K;
1264
1265 fn next(&mut self) -> Option<K> {
1266 self.inner.next().map(|(key, _)| key)
1267 }
1268
1269 fn size_hint(&self) -> (usize, Option<usize>) {
1270 self.inner.size_hint()
1271 }
1272}
1273
1274impl<'a, K: Key, V> Iterator for Values<'a, K, V> {
1275 type Item = &'a V;
1276
1277 fn next(&mut self) -> Option<&'a V> {
1278 self.inner.next().map(|(_, value)| value)
1279 }
1280
1281 fn size_hint(&self) -> (usize, Option<usize>) {
1282 self.inner.size_hint()
1283 }
1284}
1285
1286impl<'a, K: Key, V> Iterator for ValuesMut<'a, K, V> {
1287 type Item = &'a mut V;
1288
1289 fn next(&mut self) -> Option<&'a mut V> {
1290 self.inner.next().map(|(_, value)| value)
1291 }
1292
1293 fn size_hint(&self) -> (usize, Option<usize>) {
1294 self.inner.size_hint()
1295 }
1296}
1297
1298impl<'a, K: Key, V> IntoIterator for &'a HopSlotMap<K, V> {
1299 type Item = (K, &'a V);
1300 type IntoIter = Iter<'a, K, V>;
1301
1302 fn into_iter(self) -> Self::IntoIter {
1303 self.iter()
1304 }
1305}
1306
1307impl<'a, K: Key, V> IntoIterator for &'a mut HopSlotMap<K, V> {
1308 type Item = (K, &'a mut V);
1309 type IntoIter = IterMut<'a, K, V>;
1310
1311 fn into_iter(self) -> Self::IntoIter {
1312 self.iter_mut()
1313 }
1314}
1315
1316impl<K: Key, V> IntoIterator for HopSlotMap<K, V> {
1317 type Item = (K, V);
1318 type IntoIter = IntoIter<K, V>;
1319
1320 fn into_iter(self) -> Self::IntoIter {
1321 IntoIter {
1322 cur: 0,
1323 num_left: self.len(),
1324 slots: self.slots,
1325 _k: PhantomData,
1326 }
1327 }
1328}
1329
1330impl<'a, K: Key, V> FusedIterator for Iter<'a, K, V> {}
1331impl<'a, K: Key, V> FusedIterator for IterMut<'a, K, V> {}
1332impl<'a, K: Key, V> FusedIterator for Keys<'a, K, V> {}
1333impl<'a, K: Key, V> FusedIterator for Values<'a, K, V> {}
1334impl<'a, K: Key, V> FusedIterator for ValuesMut<'a, K, V> {}
1335impl<'a, K: Key, V> FusedIterator for Drain<'a, K, V> {}
1336impl<K: Key, V> FusedIterator for IntoIter<K, V> {}
1337
1338impl<'a, K: Key, V> ExactSizeIterator for Iter<'a, K, V> {}
1339impl<'a, K: Key, V> ExactSizeIterator for IterMut<'a, K, V> {}
1340impl<'a, K: Key, V> ExactSizeIterator for Keys<'a, K, V> {}
1341impl<'a, K: Key, V> ExactSizeIterator for Values<'a, K, V> {}
1342impl<'a, K: Key, V> ExactSizeIterator for ValuesMut<'a, K, V> {}
1343impl<'a, K: Key, V> ExactSizeIterator for Drain<'a, K, V> {}
1344impl<K: Key, V> ExactSizeIterator for IntoIter<K, V> {}
1345
1346// Serialization with serde.
1347#[cfg(feature = "serde")]
1348mod serialize {
1349 use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
1350
1351 use super::*;
1352
1353 #[derive(Serialize, Deserialize)]
1354 struct SerdeSlot<T> {
1355 value: Option<T>,
1356 version: u32,
1357 }
1358
1359 impl<T: Serialize> Serialize for Slot<T> {
1360 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1361 where
1362 S: Serializer,
1363 {
1364 let serde_slot = SerdeSlot {
1365 version: self.version,
1366 value: match self.get() {
1367 Occupied(value) => Some(value),
1368 Vacant(_) => None,
1369 },
1370 };
1371 serde_slot.serialize(serializer)
1372 }
1373 }
1374
1375 impl<'de, T> Deserialize<'de> for Slot<T>
1376 where
1377 T: Deserialize<'de>,
1378 {
1379 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1380 where
1381 D: Deserializer<'de>,
1382 {
1383 let serde_slot: SerdeSlot<T> = Deserialize::deserialize(deserializer)?;
1384 let occupied = serde_slot.version % 2 == 1;
1385 if occupied ^ serde_slot.value.is_some() {
1386 return Err(de::Error::custom("inconsistent occupation in Slot"));
1387 }
1388
1389 Ok(Self {
1390 u: match serde_slot.value {
1391 Some(value) => SlotUnion {
1392 value: ManuallyDrop::new(value),
1393 },
1394 None => SlotUnion {
1395 free: FreeListEntry {
1396 next: 0,
1397 prev: 0,
1398 other_end: 0,
1399 },
1400 },
1401 },
1402 version: serde_slot.version,
1403 })
1404 }
1405 }
1406
1407 impl<K: Key, V: Serialize> Serialize for HopSlotMap<K, V> {
1408 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1409 where
1410 S: Serializer,
1411 {
1412 self.slots.serialize(serializer)
1413 }
1414 }
1415
1416 impl<'de, K: Key, V: Deserialize<'de>> Deserialize<'de> for HopSlotMap<K, V> {
1417 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1418 where
1419 D: Deserializer<'de>,
1420 {
1421 let mut slots: Vec<Slot<V>> = Deserialize::deserialize(deserializer)?;
1422 if slots.len() >= u32::MAX as usize {
1423 return Err(de::Error::custom("too many slots"));
1424 }
1425
1426 // Ensure the first slot exists and is empty for the sentinel.
1427 if slots.first().map_or(true, |slot| slot.version % 2 == 1) {
1428 return Err(de::Error::custom("first slot not empty"));
1429 }
1430
1431 slots[0].u.free = FreeListEntry {
1432 next: 0,
1433 prev: 0,
1434 other_end: 0,
1435 };
1436
1437 // We have our slots, rebuild freelist.
1438 let mut num_elems = 0;
1439 let mut prev = 0;
1440 let mut i = 0;
1441 while i < slots.len() {
1442 // i is the start of a contiguous block of vacant slots.
1443 let front = i;
1444 while i < slots.len() && !slots[i].occupied() {
1445 i += 1;
1446 }
1447 let back = i - 1;
1448
1449 // Update freelist.
1450 slots[back].u.free.other_end = front as u32;
1451 slots[prev].u.free.next = front as u32;
1452 slots[front].u.free = FreeListEntry {
1453 next: 0,
1454 prev: prev as u32,
1455 other_end: back as u32,
1456 };
1457
1458 prev = front;
1459
1460 // Skip occupied slots.
1461 while i < slots.len() && slots[i].occupied() {
1462 num_elems += 1;
1463 i += 1;
1464 }
1465 }
1466
1467 Ok(Self {
1468 num_elems,
1469 slots,
1470 _k: PhantomData,
1471 })
1472 }
1473 }
1474}
1475
1476#[cfg(test)]
1477mod tests {
1478 use std::collections::{HashMap, HashSet};
1479
1480 use quickcheck::quickcheck;
1481
1482 use super::*;
1483
1484 #[derive(Clone)]
1485 struct CountDrop<'a>(&'a std::cell::RefCell<usize>);
1486
1487 impl<'a> Drop for CountDrop<'a> {
1488 fn drop(&mut self) {
1489 *self.0.borrow_mut() += 1;
1490 }
1491 }
1492
1493 #[test]
1494 fn check_drops() {
1495 let drops = std::cell::RefCell::new(0usize);
1496
1497 {
1498 let mut clone = {
1499 // Insert 1000 items.
1500 let mut sm = HopSlotMap::new();
1501 let mut sm_keys = Vec::new();
1502 for _ in 0..1000 {
1503 sm_keys.push(sm.insert(CountDrop(&drops)));
1504 }
1505
1506 // Remove even keys.
1507 for i in (0..1000).filter(|i| i % 2 == 0) {
1508 sm.remove(sm_keys[i]);
1509 }
1510
1511 // Should only have dropped 500 so far.
1512 assert_eq!(*drops.borrow(), 500);
1513
1514 // Let's clone ourselves and then die.
1515 sm.clone()
1516 };
1517
1518 // Now all original items should have been dropped exactly once.
1519 assert_eq!(*drops.borrow(), 1000);
1520
1521 // Reuse some empty slots.
1522 for _ in 0..250 {
1523 clone.insert(CountDrop(&drops));
1524 }
1525 }
1526
1527 // 1000 + 750 drops in total should have happened.
1528 assert_eq!(*drops.borrow(), 1750);
1529 }
1530
1531 #[test]
1532 fn disjoint() {
1533 // Intended to be run with miri to find any potential UB.
1534 let mut sm = HopSlotMap::new();
1535
1536 // Some churn.
1537 for i in 0..20usize {
1538 sm.insert(i);
1539 }
1540 sm.retain(|_, i| *i % 2 == 0);
1541
1542 let keys: Vec<_> = sm.keys().collect();
1543 for i in 0..keys.len() {
1544 for j in 0..keys.len() {
1545 if let Some([r0, r1]) = sm.get_disjoint_mut([keys[i], keys[j]]) {
1546 *r0 ^= *r1;
1547 *r1 = r1.wrapping_add(*r0);
1548 } else {
1549 assert!(i == j);
1550 }
1551 }
1552 }
1553
1554 for i in 0..keys.len() {
1555 for j in 0..keys.len() {
1556 for k in 0..keys.len() {
1557 if let Some([r0, r1, r2]) = sm.get_disjoint_mut([keys[i], keys[j], keys[k]]) {
1558 *r0 ^= *r1;
1559 *r0 = r0.wrapping_add(*r2);
1560 *r1 ^= *r0;
1561 *r1 = r1.wrapping_add(*r2);
1562 *r2 ^= *r0;
1563 *r2 = r2.wrapping_add(*r1);
1564 } else {
1565 assert!(i == j || j == k || i == k);
1566 }
1567 }
1568 }
1569 }
1570 }
1571
1572 quickcheck! {
1573 fn qc_slotmap_equiv_hashmap(operations: Vec<(u8, u32)>) -> bool {
1574 let mut hm = HashMap::new();
1575 let mut hm_keys = Vec::new();
1576 let mut unique_key = 0u32;
1577 let mut sm = HopSlotMap::new();
1578 let mut sm_keys = Vec::new();
1579
1580 #[cfg(not(feature = "serde"))]
1581 let num_ops = 3;
1582 #[cfg(feature = "serde")]
1583 let num_ops = 4;
1584
1585 for (op, val) in operations {
1586 match op % num_ops {
1587 // Insert.
1588 0 => {
1589 hm.insert(unique_key, val);
1590 hm_keys.push(unique_key);
1591 unique_key += 1;
1592
1593 sm_keys.push(sm.insert(val));
1594 }
1595
1596 // Delete.
1597 1 => {
1598 // 10% of the time test clear.
1599 if val % 10 == 0 {
1600 let hmvals: HashSet<_> = hm.drain().map(|(_, v)| v).collect();
1601 let smvals: HashSet<_> = sm.drain().map(|(_, v)| v).collect();
1602 if hmvals != smvals {
1603 return false;
1604 }
1605 }
1606 if hm_keys.is_empty() { continue; }
1607
1608 let idx = val as usize % hm_keys.len();
1609 if hm.remove(&hm_keys[idx]) != sm.remove(sm_keys[idx]) {
1610 return false;
1611 }
1612 }
1613
1614 // Access.
1615 2 => {
1616 if hm_keys.is_empty() { continue; }
1617 let idx = val as usize % hm_keys.len();
1618 let (hm_key, sm_key) = (&hm_keys[idx], sm_keys[idx]);
1619
1620 if hm.contains_key(hm_key) != sm.contains_key(sm_key) ||
1621 hm.get(hm_key) != sm.get(sm_key) {
1622 return false;
1623 }
1624 }
1625
1626 // Serde round-trip.
1627 #[cfg(feature = "serde")]
1628 3 => {
1629 let ser = serde_json::to_string(&sm).unwrap();
1630 sm = serde_json::from_str(&ser).unwrap();
1631 }
1632
1633 _ => unreachable!(),
1634 }
1635 }
1636
1637 let mut smv: Vec<_> = sm.values().collect();
1638 let mut hmv: Vec<_> = hm.values().collect();
1639 smv.sort();
1640 hmv.sort();
1641 smv == hmv
1642 }
1643 }
1644
1645 #[cfg(feature = "serde")]
1646 #[test]
1647 fn slotmap_serde() {
1648 let mut sm = HopSlotMap::new();
1649 // Self-referential structure.
1650 let first = sm.insert_with_key(|k| (k, 23i32));
1651 let second = sm.insert((first, 42));
1652
1653 // Make some empty slots.
1654 let empties = vec![sm.insert((first, 0)), sm.insert((first, 0))];
1655 empties.iter().for_each(|k| {
1656 sm.remove(*k);
1657 });
1658
1659 let third = sm.insert((second, 0));
1660 sm[first].0 = third;
1661
1662 let ser = serde_json::to_string(&sm).unwrap();
1663 let de: HopSlotMap<DefaultKey, (DefaultKey, i32)> = serde_json::from_str(&ser).unwrap();
1664 assert_eq!(de.len(), sm.len());
1665
1666 let mut smkv: Vec<_> = sm.iter().collect();
1667 let mut dekv: Vec<_> = de.iter().collect();
1668 smkv.sort();
1669 dekv.sort();
1670 assert_eq!(smkv, dekv);
1671 }
1672
1673 #[cfg(feature = "serde")]
1674 #[test]
1675 fn slotmap_serde_freelist() {
1676 let mut sm = HopSlotMap::new();
1677 let k = sm.insert(5i32);
1678 sm.remove(k);
1679
1680 let ser = serde_json::to_string(&sm).unwrap();
1681 let mut de: HopSlotMap<DefaultKey, i32> = serde_json::from_str(&ser).unwrap();
1682
1683 de.insert(0);
1684 de.insert(1);
1685 de.insert(2);
1686 assert_eq!(de.len(), 3);
1687 }
1688}