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}