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