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