idcontain/slab.rs
1use super::id::{Id, IdIndex, IdTag, MAXIMUM_CAPACITY};
2use rand::{self, Rng};
3use std::marker::PhantomData;
4use std::mem;
5use std::ops::{Index, IndexMut};
6use std::slice::{Iter as SliceIter, IterMut as SliceIterMut};
7
8/// An `IdSlab` stores an unordered collection of elements with fast access by opaque `Id`-s.
9///
10/// Inserting an element returns an `Id` which may later be used for lookup and deletion. It
11/// supports O(1) insertion, deletion and id-lookup. Ordering is unstable when elements are
12/// added and removed.
13///
14/// The maximum number of elements which can be stored in an `IdSlab` is `MAXIMUM_CAPACITY`
15/// (currently 2^32). This keeps `Id`-s at 64bits. A future version may support custom types for
16/// the `Id`-s making the capacity-id-size trade-off customisable.
17///
18/// Example
19/// ---
20/// ```
21/// use idcontain::{IdSlab, Id};
22///
23/// let mut id_slab: IdSlab<&'static str> = IdSlab::new();
24///
25/// // The `Id` type encodes the type of the value, to statically prevent errors caused by mixing
26/// // id-s.
27/// let hello_id: Id<&'static str> = id_slab.insert("hello");
28/// let world_id = id_slab.insert("world");
29///
30/// assert_eq!(id_slab[hello_id], "hello");
31/// assert_eq!(id_slab[world_id], "world");
32///
33/// assert_eq!(id_slab.remove(world_id), Some("world")); // The value is returned on deletion.
34/// assert!(!id_slab.contains(world_id));
35///
36/// // New id-s are different from previous ones, even though the memory is reused.
37/// let new_world_id = id_slab.insert("new world");
38/// assert!(new_world_id != world_id);
39/// ```
40///
41/// Id Reuse
42/// ---
43/// Removing an `Id` will cause future lookups with that `Id` to fail (either returning `None` for
44/// `get` and `remove`, or panicking for indexing), but this feature is 'best-effort' and should
45/// not be relied on for memory safety or security.
46///
47/// In particular removing and adding an element 2^32 times will cause that `Id` to be reused. This
48/// is, for most workloads unlikely and is made even less likely when operations are more mixed
49/// (adding more elements and removing them in between).
50///
51///
52/// Id Mixing
53/// ---
54/// Using an `Id` from a different `IdSlab` will fail at compile time, unless both `IdSlab`-s are of
55/// the same type. You are encouraged to newtype liberally to make leverage this as much as
56/// possible.
57///
58/// When using `Id`-s of the same type, lookups are still most likely going to fail at runtime:
59///
60/// ```
61/// # use idcontain::IdSlab;
62/// let mut id_slab_1 = IdSlab::new();
63/// let id1 = id_slab_1.insert(1);
64///
65/// let mut id_slab_2 = IdSlab::new();
66/// let id2 = id_slab_2.insert(1);
67///
68/// assert!(id1 != id2);
69/// assert!(!id_slab_1.contains(id2));
70/// assert!(!id_slab_2.contains(id1));
71/// ```
72///
73/// The mechanism behind this is built on the same tagging mechanism used for preventing `Id` reuse
74/// of the same `IdSlab`. As such, this feature is also best-effort and should not be used for
75/// memory safety or security.
76///
77/// For all other situations, it's probably fine. The probability curve follows the birthday
78/// paradox equation with `m=2^32 / avg_num_elements_per_id_slab` and `n=num_id_slabs`. So, for
79/// instance, 10 `IdSlab`-s with 1000 elements each, gives a collision probability of about
80/// `(n^2/2m) = 0.001%` or 1 in 100,000.
81#[derive(Clone, Debug)]
82pub struct IdSlab<T> {
83 slots: Vec<TaggedSlot<T>>,
84 first_free: IdIndex,
85 seed_tag: IdTag,
86 len: usize,
87}
88
89impl<T> IdSlab<T> {
90 /// Creates a new `IdSlab` with zero capacity.
91 ///
92 /// The first insertion will cause an allocation.
93 pub fn new() -> Self {
94 Self::with_capacity(0)
95 }
96
97 /// Creates a new `IdSlab` with a given capacity.
98 ///
99 /// As long as number of elements stays under this capacity, no re-allocation will be
100 /// triggered.
101 pub fn with_capacity(capacity: usize) -> Self {
102 Self::with_capacity_and_seed_tag(capacity, default_seed_tag())
103 }
104
105 /// Creates a new `IdSlab` with a given capacity and seed tag.
106 ///
107 /// This is an advanced feature which may cause more `Id` collisions between your `IdSlab`-s if
108 /// used incorrectly.
109 ///
110 /// The `seed_tag` of an `IdSlab` is the tag assigned to new slots. Removing elements increments
111 /// this tag and wraps around, providing the mechanism for `Id` reuse prevention and `Id`
112 /// mixing detection.
113 ///
114 /// The `new` and `with_capacity` constructors set the seed tag to a random number, but better
115 /// strategies exist for preventing collisions if you know your workload.
116 pub fn with_capacity_and_seed_tag(capacity: usize, seed_tag: IdTag) -> Self {
117 assert!(capacity <= MAXIMUM_CAPACITY);
118
119 IdSlab {
120 slots: if capacity == 0 {
121 Vec::new()
122 } else {
123 Vec::with_capacity(capacity)
124 },
125 first_free: 0,
126 seed_tag: seed_tag,
127 len: 0,
128 }
129 }
130
131 /// Returns the number of elements in the `IdSlab`.
132 ///
133 /// Panics
134 /// ---
135 /// None.
136 ///
137 /// Example
138 /// ---
139 /// ```
140 /// # use idcontain::IdSlab;
141 /// let mut id_slab = IdSlab::new();
142 /// assert_eq!(id_slab.len(), 0);
143 ///
144 /// let id = id_slab.insert(1);
145 /// assert_eq!(id_slab.len(), 1);
146 ///
147 /// id_slab.remove(id);
148 /// assert_eq!(id_slab.len(), 0);
149 /// ```
150 pub fn len(&self) -> usize {
151 self.len
152 }
153
154 /// Returns true if the slab is empty.
155 ///
156 /// Panics
157 /// ---
158 /// None.
159 ///
160 /// Example
161 /// ---
162 /// ```
163 /// # use idcontain::IdSlab;
164 /// let mut id_slab = IdSlab::new();
165 /// assert!(id_slab.is_empty());
166 ///
167 /// let id = id_slab.insert(1);
168 /// assert!(!id_slab.is_empty());
169 ///
170 /// id_slab.remove(id);
171 /// assert!(id_slab.is_empty());
172 /// ```
173 pub fn is_empty(&self) -> bool {
174 self.len == 0
175 }
176
177 /// Returns `true` if there exists an element with the given `Id`.
178 ///
179 /// See struct-level docs for caveats about `Id` reuse and mixing (almost always fine, but
180 /// `contains` may give you false positives in pathological cases so don't rely on it for
181 /// memory safety or security).
182 ///
183 /// Panics
184 /// ---
185 /// None.
186 ///
187 /// Example
188 /// ---
189 /// ```
190 /// # use idcontain::IdSlab;
191 /// let mut id_slab = IdSlab::new();
192 /// assert_eq!(id_slab.len(), 0);
193 ///
194 /// let id = id_slab.insert(1);
195 /// assert!(id_slab.contains(id));
196 ///
197 /// id_slab.remove(id);
198 /// assert!(!id_slab.contains(id));
199 /// ```
200 pub fn contains(&self, id: Id<T>) -> bool {
201 match self.slots.get(id.index as usize) {
202 Some(&TaggedSlot {
203 slot: Slot::Occupied { .. },
204 tag,
205 }) if tag == id.tag => true,
206 _ => false,
207 }
208 }
209
210 /// Returns a reference to an element by `Id` or `None` if it doesn't exist.
211 ///
212 /// Use indexing for a panicking version of this operation.
213 ///
214 /// Panics
215 /// ---
216 /// None.
217 ///
218 /// Example
219 /// ---
220 /// ```
221 /// # use idcontain::IdSlab;
222 /// let mut id_slab = IdSlab::new();
223 /// let id = id_slab.insert(1);
224 ///
225 /// assert_eq!(id_slab.get(id), Some(&1));
226 ///
227 /// id_slab.remove(id);
228 /// assert_eq!(id_slab.get(id), None);
229 /// ```
230 pub fn get(&self, id: Id<T>) -> Option<&T> {
231 self.get_or_tagged_slot(id).ok()
232 }
233
234 /// Returns a mutable reference to an element by `Id` or `None` if it doesn't exist.
235 ///
236 /// Use indexing for a panicking version of this operation.
237 ///
238 /// Panics
239 /// ---
240 /// None.
241 ///
242 /// Example
243 /// ---
244 /// ```
245 /// # use idcontain::IdSlab;
246 /// let mut id_slab = IdSlab::new();
247 /// let id = id_slab.insert(1);
248 ///
249 /// *id_slab.get_mut(id).unwrap() = 10;
250 /// assert_eq!(id_slab[id], 10);
251 ///
252 /// id_slab.remove(id);
253 /// assert_eq!(id_slab.get_mut(id), None);
254 /// ```
255 pub fn get_mut(&mut self, id: Id<T>) -> Option<&mut T> {
256 self.get_mut_or_tagged_slot(id).ok()
257 }
258
259 /// Inserts a new element into the `IdSlab`, returning its `Id<T>`.
260 ///
261 /// In general the `Id`-s do not get reused and should not collide with other `IdSlab`-s, but
262 /// caveats apply, see the struct-level doc for more details.
263 ///
264 /// Panics
265 /// ---
266 /// If `self.len() == MAXIMUM_CAPACITY`.
267 ///
268 ///
269 /// Example
270 /// ---
271 /// ```
272 /// # use idcontain::IdSlab;
273 /// let mut id_slab = IdSlab::new();
274 /// let id1 = id_slab.insert(1);
275 /// let id2 = id_slab.insert(2);
276 ///
277 /// assert_eq!(id_slab[id1], 1);
278 /// assert_eq!(id_slab[id2], 2);
279 ///
280 /// // Id-s are not (caveats apply) shared between `IdSlab`-s.
281 /// let mut new_id_slab = IdSlab::new();
282 /// let new_id1 = new_id_slab.insert(1);
283 /// assert!(new_id1 != id1);
284 ///
285 /// // Id-s are not (caveats apply) reused.
286 /// id_slab.remove(id1);
287 /// let id3 = id_slab.insert(3);
288 /// assert!(id3 != id1);
289 /// ```
290 pub fn insert(&mut self, value: T) -> Id<T> {
291 assert!(self.len() < MAXIMUM_CAPACITY);
292
293 self.len += 1;
294 if self.first_free < self.slots.len() as IdIndex {
295 let index = self.first_free;
296 let tagged_slot = &mut self.slots[self.first_free as usize];
297 match mem::replace(&mut tagged_slot.slot, Slot::Occupied { value: value }) {
298 Slot::Free { next_free } => self.first_free = next_free,
299 Slot::Occupied { .. } => panic!("Occupied slot in free list."),
300 }
301 Id {
302 tag: tagged_slot.tag,
303 index: index,
304 _data: PhantomData,
305 }
306 } else {
307 self.slots.push(TaggedSlot {
308 tag: self.seed_tag,
309 slot: Slot::Occupied { value: value },
310 });
311 self.first_free = self.slots.len() as IdIndex;
312 Id {
313 index: self.first_free - 1,
314 tag: self.seed_tag,
315 _data: PhantomData,
316 }
317 }
318 }
319
320 /// Removes an element by `Id` returning its value.
321 ///
322 /// Returns `None` if no element with the given `Id` exists. See the struct level docs for the
323 /// pathological cases where this may not be the case.
324 ///
325 /// Panics
326 /// ---
327 /// None.
328 ///
329 /// Example
330 /// ---
331 /// ```
332 /// # use idcontain::IdSlab;
333 /// let mut id_slab = IdSlab::new();
334 /// let id1 = id_slab.insert(1);
335 ///
336 /// assert_eq!(id_slab[id1], 1);
337 /// assert_eq!(id_slab.remove(id1), Some(1));
338 ///
339 /// assert!(!id_slab.contains(id1));
340 /// assert_eq!(id_slab.remove(id1), None);
341 /// ```
342 pub fn remove(&mut self, id: Id<T>) -> Option<T> {
343 let IdSlab {
344 ref mut slots,
345 ref mut len,
346 ref mut first_free,
347 ..
348 } = *self;
349 slots.get_mut(id.index as usize).and_then(|tagged_slot| {
350 if tagged_slot.tag == id.tag {
351 match mem::replace(
352 &mut tagged_slot.slot,
353 Slot::Free {
354 next_free: *first_free,
355 },
356 ) {
357 Slot::Occupied { value } => {
358 *len = len.checked_sub(1).expect("invalid len in remove()");
359 tagged_slot.tag = tagged_slot.tag.wrapping_add(1);
360 *first_free = id.index;
361 Some(value)
362 }
363 rollback @ Slot::Free { .. } => {
364 tagged_slot.slot = rollback;
365 None
366 }
367 }
368 } else {
369 None
370 }
371 })
372 }
373
374 /// Iterates over references to the elements in the `IdSlab`.
375 ///
376 /// While this operation has good cache locality, its worst-case complexity is
377 /// `O(max_number_of_elements_ever)`. I.e. there are pathological cases where adding and
378 /// removing 1 million elements, then adding one element back will cause iteration to be `O(1
379 /// million)`.
380 ///
381 /// The iteration order is unspecified, but it doesn't change unless the `IdSlab` is mutated.
382 ///
383 /// Panics
384 /// ---
385 /// None.
386 ///
387 /// Example
388 /// ---
389 /// ```
390 /// # use idcontain::IdSlab;
391 /// let mut id_slab = IdSlab::new();
392 /// id_slab.insert(1);
393 /// id_slab.insert(2);
394 /// id_slab.insert(3);
395 ///
396 /// for i in id_slab.iter() {
397 /// println!("{}", i); // Prints 1, 2, 3.
398 /// }
399 ///
400 /// // Can use `&id_slab` instead:
401 /// for i in &id_slab {
402 /// println!("{}", i); // Prints 1, 2, 3.
403 /// }
404 /// ```
405 pub fn iter(&self) -> Iter<T> {
406 Iter {
407 num_left: self.len(),
408 iter: self.slots.iter(),
409 }
410 }
411
412 /// Iterates over mutable references to the elements in the `IdSlab`.
413 ///
414 /// See `iter` for notes on complexity and iteration order.
415 ///
416 /// Panics
417 /// ---
418 /// None.
419 ///
420 /// Example
421 /// ---
422 /// ```
423 /// # use idcontain::IdSlab;
424 /// let mut id_slab = IdSlab::new();
425 /// id_slab.insert(1);
426 /// id_slab.insert(2);
427 /// id_slab.insert(3);
428 ///
429 /// for value in id_slab.iter_mut() { // Or `&mut id_slab`.
430 /// *value += 1;
431 /// }
432 ///
433 /// for i in &id_slab {
434 /// println!("{}", i); // Prints 2, 3, 4.
435 /// }
436 /// ```
437 pub fn iter_mut(&mut self) -> IterMut<T> {
438 IterMut {
439 num_left: self.len(),
440 iter: self.slots.iter_mut(),
441 }
442 }
443
444 fn get_or_tagged_slot(&self, id: Id<T>) -> Result<&T, Option<&TaggedSlot<T>>> {
445 match self.slots.get(id.index as usize) {
446 Some(&TaggedSlot {
447 slot: Slot::Occupied { ref value },
448 tag,
449 }) if tag == id.tag => Ok(value),
450 tagged_slot => Err(tagged_slot),
451 }
452 }
453
454 fn get_mut_or_tagged_slot(&mut self, id: Id<T>) -> Result<&mut T, Option<&mut TaggedSlot<T>>> {
455 match self.slots.get_mut(id.index as usize) {
456 Some(tagged_slot) => {
457 if id.tag == tagged_slot.tag {
458 match tagged_slot.slot {
459 Slot::Occupied { ref mut value } => Ok(value),
460 _ => Err(Some(tagged_slot)),
461 }
462 } else {
463 Err(Some(tagged_slot))
464 }
465 }
466 _ => Err(None),
467 }
468 }
469
470 /// Returns a reference to an element by index or `None` if it doesn't exist.
471 ///
472 /// This is a low-level operation that bypasses the tag check. Useful for building other
473 /// containers on top.
474 ///
475 /// Panics
476 /// ---
477 /// None.
478 ///
479 /// Example
480 /// ---
481 /// ```
482 /// # use idcontain::IdSlab;
483 /// let mut id_slab = IdSlab::new();
484 /// let id = id_slab.insert(1);
485 ///
486 /// assert_eq!(id_slab.by_index(0), Some(&1));
487 /// ```
488 pub fn by_index(&self, index: IdIndex) -> Option<&T> {
489 match self.slots.get(index as usize) {
490 Some(&TaggedSlot {
491 slot: Slot::Occupied { ref value },
492 ..
493 }) => Some(value),
494 _ => None,
495 }
496 }
497
498 /// Returns a mutable reference to an element by index or `None` if it doesn't exist.
499 ///
500 /// This is a low-level operation that bypasses the tag check. Useful for building other
501 /// containers on top.
502 ///
503 /// Panics
504 /// ---
505 /// None.
506 ///
507 /// Example
508 /// ---
509 /// ```
510 /// # use idcontain::IdSlab;
511 /// let mut id_slab = IdSlab::new();
512 /// let id = id_slab.insert(1);
513 ///
514 /// *id_slab.by_index_mut(0).unwrap() = 10;
515 /// assert_eq!(id_slab[id], 10);
516 /// ```
517 pub fn by_index_mut(&mut self, index: IdIndex) -> Option<&mut T> {
518 match self.slots.get_mut(index as usize) {
519 Some(&mut TaggedSlot {
520 slot: Slot::Occupied { ref mut value },
521 ..
522 }) => Some(value),
523 _ => None,
524 }
525 }
526
527 /// Returns the `Id` for a given occupied index.
528 ///
529 /// Returns `None` if the index is invalid.
530 ///
531 /// This is a low-level operation that bypasses the tag check. Useful for building other
532 /// containers on top.
533 ///
534 /// Panics
535 /// ---
536 /// None.
537 ///
538 /// Example
539 /// ---
540 /// ```
541 /// # use idcontain::IdSlab;
542 /// let mut id_slab = IdSlab::new();
543 /// let id = id_slab.insert(1);
544 ///
545 /// assert_eq!(id_slab.index_to_id(0), Some(id));
546 /// ```
547 pub fn index_to_id(&self, index: IdIndex) -> Option<Id<T>> {
548 match self.slots.get(index as usize) {
549 Some(&TaggedSlot {
550 slot: Slot::Occupied { .. },
551 tag,
552 }) => Some(Id {
553 index: index,
554 tag: tag,
555 _data: PhantomData,
556 }),
557 _ => None,
558 }
559 }
560}
561
562impl<T> Default for IdSlab<T> {
563 fn default() -> Self {
564 Self::new()
565 }
566}
567
568#[cold]
569#[inline(never)]
570fn panic_for_bad_id<T>(
571 num_slots: usize,
572 seed_tag: IdTag,
573 len: usize,
574 tagged_slot: Option<&TaggedSlot<T>>,
575 id: Id<T>,
576) -> ! {
577 let reason = if id.index as usize > num_slots {
578 format!(
579 "index `{}` larger than number of slots `{}` (wrong `IdSlab`?)",
580 id.index, num_slots
581 )
582 } else if let Some(&TaggedSlot { tag, ref slot }) = tagged_slot {
583 if tag > id.tag {
584 if (tag - id.tag) < 100 {
585 format!("tag `{}` older than slot tag `{}`, deleted?", id.tag, tag)
586 } else {
587 format!(
588 "tag `{}` much older than slot tag `{}`, wrong `IdSlab` or deleted?",
589 id.tag, tag
590 )
591 }
592 } else if tag < id.tag {
593 format!(
594 "tag `{}` newer than slot tag `{}`, wrong `IdSlab`?",
595 id.tag, tag
596 )
597 } else {
598 match *slot {
599 Slot::Free { .. } => format!(
600 "tag `{}` matches, but the slot is free, wrong `IdSlab` with same \
601 seed_tag `{}`?",
602 id.tag, seed_tag
603 ),
604 Slot::Occupied { .. } => "<IdSlab bug [occupied], please report!>".to_owned(),
605 }
606 }
607 } else {
608 "<IdSlab bug [no TaggedSlot], please report!>".to_owned()
609 };
610 panic!(
611 "Invalid id: {} (id={{ index=`{}`, tag=`{}` }}, id_slab={{ num_slots=`{}`, \
612 seed_tag=`{}`, len=`{}` }})",
613 reason, id.index, id.tag, num_slots, seed_tag, len
614 )
615}
616
617impl<T> Index<Id<T>> for IdSlab<T> {
618 type Output = T;
619
620 fn index(&self, id: Id<T>) -> &Self::Output {
621 self.get_or_tagged_slot(id).unwrap_or_else(|tagged_slot| {
622 panic_for_bad_id(self.slots.len(), self.seed_tag, self.len, tagged_slot, id)
623 })
624 }
625}
626
627impl<T> IndexMut<Id<T>> for IdSlab<T> {
628 fn index_mut(&mut self, id: Id<T>) -> &mut Self::Output {
629 let num_slots = self.slots.len();
630 let &mut IdSlab { seed_tag, len, .. } = self;
631 self.get_mut_or_tagged_slot(id)
632 .unwrap_or_else(|tagged_slot| {
633 panic_for_bad_id(
634 num_slots,
635 seed_tag,
636 len,
637 tagged_slot.map(|tagged_slot| &*tagged_slot),
638 id,
639 )
640 })
641 }
642}
643
644/// The type returned by `IdSlab.iter()`.
645#[derive(Clone, Debug)]
646pub struct Iter<'a, T: 'a> {
647 num_left: usize,
648 iter: SliceIter<'a, TaggedSlot<T>>,
649}
650
651impl<'a, T: 'a> Iterator for Iter<'a, T> {
652 type Item = &'a T;
653
654 fn next(&mut self) -> Option<Self::Item> {
655 while self.num_left > 0 {
656 let tagged_slot = self.iter.next().expect("Too few elements in Iter");
657 if let TaggedSlot {
658 slot: Slot::Occupied { ref value },
659 ..
660 } = *tagged_slot
661 {
662 self.num_left -= 1;
663 return Some(value);
664 }
665 }
666 None
667 }
668
669 fn size_hint(&self) -> (usize, Option<usize>) {
670 (self.num_left, Some(self.num_left))
671 }
672}
673
674impl<'a, T: 'a> DoubleEndedIterator for Iter<'a, T> {
675 fn next_back(&mut self) -> Option<Self::Item> {
676 while self.num_left > 0 {
677 let tagged_slot = self.iter.next_back().expect("Too few elements in Iter");
678 if let TaggedSlot {
679 slot: Slot::Occupied { ref value },
680 ..
681 } = *tagged_slot
682 {
683 self.num_left -= 1;
684 return Some(value);
685 }
686 }
687 None
688 }
689}
690
691impl<'a, T: 'a> ExactSizeIterator for Iter<'a, T> {
692 fn len(&self) -> usize {
693 self.num_left
694 }
695}
696
697fn default_seed_tag() -> IdTag {
698 rand::thread_rng().gen()
699}
700
701/// The type returned by `IdSlab.iter_mut()`.
702#[derive(Debug)]
703pub struct IterMut<'a, T: 'a> {
704 iter: SliceIterMut<'a, TaggedSlot<T>>,
705 num_left: usize,
706}
707
708impl<'a, T: 'a> Iterator for IterMut<'a, T> {
709 type Item = &'a mut T;
710
711 fn next(&mut self) -> Option<Self::Item> {
712 while self.num_left > 0 {
713 let tagged_slot = self.iter.next().expect("Too few elements in IterMut");
714 if let TaggedSlot {
715 slot: Slot::Occupied { ref mut value },
716 ..
717 } = *tagged_slot
718 {
719 self.num_left -= 1;
720 return Some(value);
721 }
722 }
723 None
724 }
725
726 fn size_hint(&self) -> (usize, Option<usize>) {
727 (self.num_left, Some(self.num_left))
728 }
729}
730
731impl<'a, T: 'a> DoubleEndedIterator for IterMut<'a, T> {
732 fn next_back(&mut self) -> Option<Self::Item> {
733 while self.num_left > 0 {
734 let tagged_slot = self.iter.next_back().expect("Too few elements in IterMut");
735 if let TaggedSlot {
736 slot: Slot::Occupied { ref mut value },
737 ..
738 } = *tagged_slot
739 {
740 self.num_left -= 1;
741 return Some(value);
742 }
743 }
744 None
745 }
746}
747
748impl<'a, T: 'a> ExactSizeIterator for IterMut<'a, T> {
749 fn len(&self) -> usize {
750 self.num_left
751 }
752}
753
754impl<'a, T: 'a> IntoIterator for &'a IdSlab<T> {
755 type IntoIter = Iter<'a, T>;
756 type Item = <Self::IntoIter as Iterator>::Item;
757
758 fn into_iter(self) -> Self::IntoIter {
759 self.iter()
760 }
761}
762
763impl<'a, T: 'a> IntoIterator for &'a mut IdSlab<T> {
764 type IntoIter = IterMut<'a, T>;
765 type Item = <Self::IntoIter as Iterator>::Item;
766
767 fn into_iter(self) -> Self::IntoIter {
768 self.iter_mut()
769 }
770}
771
772#[derive(Debug, Clone)]
773enum Slot<T> {
774 Free { next_free: IdIndex },
775 Occupied { value: T },
776}
777
778#[derive(Debug, Clone)]
779struct TaggedSlot<T> {
780 tag: IdTag,
781 slot: Slot<T>,
782}
783
784#[cfg(test)]
785mod tests {
786 use super::super::id::Id;
787 use super::IdSlab;
788 use std::marker::PhantomData;
789
790 #[test]
791 fn len_iter_contains_on_empty() {
792 let id_slab = IdSlab::<i32>::new();
793 assert_eq!(id_slab.len(), 0);
794 assert_eq!(id_slab.iter().next(), None);
795 assert!(!id_slab.contains(Id {
796 index: 0,
797 tag: 0,
798 _data: PhantomData,
799 }));
800 }
801
802 #[test]
803 fn iter_mut_on_empty() {
804 let mut id_slab = IdSlab::<String>::new();
805 assert_eq!(id_slab.iter_mut().next(), None);
806 }
807
808 #[test]
809 fn id_slab_insert_then_get_and_index() {
810 let mut id_slab = IdSlab::new();
811
812 let id_a = id_slab.insert(1);
813 let id_b = id_slab.insert(2);
814 let id_c = id_slab.insert(3);
815
816 // Id-s all differ from each other.
817 assert!(id_a != id_b);
818 assert!(id_b != id_c);
819 assert!(id_c != id_a);
820
821 // `get` returns the correct values.
822 assert_eq!(id_slab.get(id_a).map(|&x| x), Some(1));
823 assert_eq!(id_slab.get(id_b).map(|&x| x), Some(2));
824 assert_eq!(id_slab.get(id_c).map(|&x| x), Some(3));
825
826 // `get_mut` returns the correct values.
827 assert_eq!(id_slab.get_mut(id_a).map(|&mut x| x), Some(1));
828 assert_eq!(id_slab.get_mut(id_b).map(|&mut x| x), Some(2));
829 assert_eq!(id_slab.get_mut(id_c).map(|&mut x| x), Some(3));
830
831 // `index` returns the correct values.
832 assert_eq!(*(&id_slab[id_a]), 1);
833 assert_eq!(*(&id_slab[id_b]), 2);
834 assert_eq!(*(&id_slab[id_c]), 3);
835
836 // `index` returns the correct values.
837 assert_eq!(*(&mut id_slab[id_a]), 1);
838 assert_eq!(*(&mut id_slab[id_b]), 2);
839 assert_eq!(*(&mut id_slab[id_c]), 3);
840
841 // Mutating through id_b then `get`-ing again works.
842 id_slab[id_b] = 10;
843 assert_eq!(id_slab[id_b], 10);
844 }
845
846 #[test]
847 #[should_panic]
848 fn id_slab_insert_then_remove_index_panics() {
849 let mut id_slab = IdSlab::new();
850 let id = id_slab.insert(1);
851 id_slab.remove(id);
852 id_slab[id];
853 }
854
855 #[test]
856 #[should_panic]
857 fn id_slab_insert_then_remove_index_mut_panics() {
858 let mut id_slab = IdSlab::new();
859 let id = id_slab.insert(1);
860 id_slab.remove(id);
861 id_slab[id] = 10;
862 }
863
864 #[test]
865 fn id_slab_insert_then_remove_get() {
866 let mut id_slab = IdSlab::with_capacity(3);
867
868 let id_a = id_slab.insert(1);
869 let id_b = id_slab.insert(2);
870 let id_c = id_slab.insert(3);
871
872 assert_eq!(id_slab.remove(id_b), Some(2));
873 assert_eq!(id_slab.get(id_b), None);
874 assert!(!id_slab.contains(id_b));
875
876 assert_eq!(id_slab[id_a], 1);
877 assert_eq!(id_slab[id_c], 3);
878
879 let id_d = id_slab.insert(5);
880
881 assert_eq!(id_slab.remove(id_a), Some(1));
882 assert_eq!(id_slab.remove(id_a), None);
883 assert_eq!(id_slab.remove(id_c), Some(3));
884 assert_eq!(id_slab.get(id_a), None);
885 assert_eq!(id_slab.get(id_c), None);
886 assert!(!id_slab.contains(id_a));
887 assert!(!id_slab.contains(id_b));
888 assert!(!id_slab.contains(id_c));
889 assert!(id_slab.contains(id_d));
890
891 let id_e = id_slab.insert(6);
892 let id_f = id_slab.insert(7);
893
894 assert!(id_d.tag == id_b.tag.wrapping_add(1));
895 assert!(id_d.index == id_b.index);
896
897 assert!(id_e.tag == id_c.tag.wrapping_add(1));
898 assert!(id_e.index == id_c.index);
899
900 assert!(id_f.tag == id_a.tag.wrapping_add(1));
901 assert!(id_f.index == id_a.index);
902 }
903
904 #[test]
905 fn id_slab_insert_then_remove_iter() {
906 let mut id_slab = IdSlab::with_capacity(3);
907
908 let id_a = id_slab.insert(1);
909 let id_b = id_slab.insert(2);
910 id_slab.insert(3);
911 id_slab.remove(id_b);
912 id_slab.insert(4);
913 let id_e = id_slab.insert(5);
914 id_slab.remove(id_e);
915 id_slab.remove(id_a);
916
917 assert_eq!(&id_slab.iter().cloned().collect::<Vec<_>>()[..], &[4, 3]);
918 assert_eq!(
919 &id_slab.iter_mut().map(|&mut x| x).collect::<Vec<_>>()[..],
920 &[4, 3]
921 );
922
923 assert_eq!(
924 &(&id_slab).into_iter().cloned().collect::<Vec<_>>()[..],
925 &[4, 3]
926 );
927 assert_eq!(
928 &(&mut id_slab)
929 .into_iter()
930 .map(|&mut x| x)
931 .collect::<Vec<_>>()[..],
932 &[4, 3]
933 );
934 }
935
936 #[test]
937 fn id_slab_ids_from_different_id_slabs() {
938 let mut id_slab_1 = IdSlab::with_capacity(3);
939 let mut id_slab_2 = IdSlab::with_capacity(4);
940
941 let id_a_1 = id_slab_1.insert(1);
942 let id_b_1 = id_slab_1.insert(2);
943 let id_c_1 = id_slab_1.insert(3);
944
945 let id_a_2 = id_slab_2.insert(1);
946 let id_b_2 = id_slab_2.insert(2);
947 let id_c_2 = id_slab_2.insert(3);
948 let id_d_2 = id_slab_2.insert(4);
949
950 assert_eq!(id_slab_1.get(id_a_2), None);
951 assert_eq!(id_slab_1.get(id_b_2), None);
952 assert_eq!(id_slab_1.get(id_c_2), None);
953 assert_eq!(id_slab_1.get(id_d_2), None);
954 assert_eq!(id_slab_1.get_mut(id_a_2), None);
955 assert_eq!(id_slab_1.get_mut(id_b_2), None);
956 assert_eq!(id_slab_1.get_mut(id_c_2), None);
957 assert_eq!(id_slab_1.get_mut(id_d_2), None);
958 assert!(!id_slab_1.contains(id_a_2));
959 assert!(!id_slab_1.contains(id_b_2));
960 assert!(!id_slab_1.contains(id_c_2));
961 assert!(!id_slab_1.contains(id_d_2));
962 assert_eq!(id_slab_1.remove(id_a_2), None);
963 assert_eq!(id_slab_1.remove(id_b_2), None);
964 assert_eq!(id_slab_1.remove(id_c_2), None);
965 assert_eq!(id_slab_1.remove(id_d_2), None);
966 assert_eq!(&id_slab_1.iter().cloned().collect::<Vec<_>>(), &[1, 2, 3]);
967
968 assert_eq!(id_slab_2.get(id_a_1), None);
969 assert_eq!(id_slab_2.get(id_b_1), None);
970 assert_eq!(id_slab_2.get(id_c_1), None);
971 assert_eq!(id_slab_2.get_mut(id_a_1), None);
972 assert_eq!(id_slab_2.get_mut(id_b_1), None);
973 assert_eq!(id_slab_2.get_mut(id_c_1), None);
974 assert!(!id_slab_2.contains(id_a_1));
975 assert!(!id_slab_2.contains(id_b_1));
976 assert!(!id_slab_2.contains(id_c_1));
977 assert_eq!(id_slab_2.remove(id_a_1), None);
978 assert_eq!(id_slab_2.remove(id_b_1), None);
979 assert_eq!(id_slab_2.remove(id_c_1), None);
980 assert_eq!(
981 &id_slab_2.iter().cloned().collect::<Vec<_>>(),
982 &[1, 2, 3, 4]
983 );
984 }
985}