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