slabbable_stablevec/
lib.rs

1#![warn(
2    clippy::unwrap_used,
3    missing_docs,
4    rust_2018_idioms,
5    unused_lifetimes,
6    unused_qualifications
7)]
8#![allow(clippy::single_match, rustdoc::bare_urls)]
9#![cfg_attr(all(not(feature = "std"), not(test)), no_std)]
10#![doc = include_str!("../README.md")]
11
12//! StableVec does not shift elements upon deletion and has stable index
13//! and does not invalide indexes upon that happening.
14//!
15//! We are not concerned about continuous memory since we are not iterating
16//! or sorting our collection.
17//!
18//! This impl of StableVec re-uses idx unlike impl that keeps track of rotating
19//! index within.
20
21use slabbable::{ReservedSlot, Slabbable, SlabbableError};
22
23#[derive(Debug)]
24enum ReserveStatus<Item> {
25    Reserved,
26    Taken(Item),
27}
28
29use stable_vec::{core::BitVecCore, StableVecFacade};
30
31/// Holder
32#[derive(Debug)]
33pub struct StableVecSlab<Item> {
34    inner: StableVecFacade<ReserveStatus<Item>, BitVecCore<ReserveStatus<Item>>>,
35}
36
37impl<Item> Slabbable<StableVecSlab<Item>, Item> for StableVecSlab<Item>
38where
39    Item: core::fmt::Debug + Clone,
40{
41    type Error = SlabbableError;
42    /// See trait
43    fn with_fixed_capacity(cap: usize) -> Result<Self, Self::Error> {
44        Ok(Self {
45            inner: StableVecFacade::<ReserveStatus<Item>, BitVecCore<ReserveStatus<Item>>>::with_capacity(cap),
46        })
47    }
48    /// See trait
49    #[inline]
50    fn reserve_next(&mut self) -> Result<ReservedSlot, Self::Error> {
51        // Slab re-allocators upon grow - we want stable addresses
52        if self.inner.capacity() < self.inner.num_elements() + 1 {
53            return Err(SlabbableError::AtCapacity(self.inner.capacity()));
54        }
55        let ins = self.inner.push(ReserveStatus::Reserved);
56        Ok(ReservedSlot::issue(ins))
57    }
58    #[inline]
59    fn take_reserved_with(
60        &mut self,
61        r_slot: ReservedSlot,
62        with: Item,
63    ) -> Result<usize, Self::Error> {
64        let slot = r_slot.id();
65
66        let v = match self.inner.get_mut(slot) {
67            Some(v) => match v {
68                ReserveStatus::Reserved => v,
69                _ => return Err(SlabbableError::InvalidIndex(slot)),
70            },
71            _ => return Err(SlabbableError::InvalidIndex(slot)),
72        };
73        *v = ReserveStatus::Taken(with);
74        Ok(slot)
75    }
76    /// See trait
77    #[inline]
78    fn take_next_with(&mut self, with: Item) -> Result<usize, Self::Error> {
79        let reserved_slot = self.reserve_next()?;
80        self.take_reserved_with(reserved_slot, with)
81    }
82    /// See trait
83    #[inline]
84    fn mark_for_reuse(&mut self, slot: usize) -> Result<Item, Self::Error> {
85        if slot > self.inner.capacity() {
86            return Err(SlabbableError::InvalidIndex(slot));
87        }
88        match self.inner.remove(slot) {
89            Some(ReserveStatus::Taken(i)) => Ok(i),
90            _ => Err(SlabbableError::InvalidIndex(slot)),
91        }
92    }
93    /// See trait
94    #[inline]
95    fn slot_get_ref(&self, slot: usize) -> Result<Option<&Item>, Self::Error> {
96        if slot > self.inner.capacity() {
97            return Err(SlabbableError::InvalidIndex(slot));
98        }
99        match self.inner.get(slot) {
100            Some(ReserveStatus::Taken(itm_ref)) => Ok(Some(itm_ref)),
101            _ => Err(SlabbableError::InvalidIndex(slot)),
102        }
103    }
104    /// See trait
105    #[inline]
106    fn slot_get_mut(&mut self, slot: usize) -> Result<Option<&mut Item>, Self::Error> {
107        if slot > self.inner.capacity() {
108            return Err(SlabbableError::InvalidIndex(slot));
109        }
110        match self.inner.get_mut(slot) {
111            Some(ReserveStatus::Taken(itm_ref)) => Ok(Some(itm_ref)),
112            _ => Err(SlabbableError::InvalidIndex(slot)),
113        }
114    }
115    /// See trait
116    #[inline]
117    fn capacity(&self) -> usize {
118        self.inner.capacity()
119    }
120    /// See trait
121    #[inline]
122    fn remaining(&self) -> Option<usize> {
123        let rem = self.inner.capacity() - self.inner.num_elements();
124        match rem {
125            0 => None,
126            1_usize.. => Some(rem),
127        }
128    }
129    /// See trait
130    fn reap(&mut self) -> Option<usize> {
131        // We don't support it
132        None
133    }
134}