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}