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
12use slab::Slab;
13use slabbable::{ReservedSlot, Slabbable, SlabbableError};
14
15#[derive(Debug)]
16enum ReserveStatus<Item> {
17 Reserved,
18 Taken(Item),
19}
20
21#[derive(Debug)]
23pub struct SlabSlab<Item> {
24 inner: Slab<ReserveStatus<Item>>,
25}
26
27impl<Item> Slabbable<SlabSlab<Item>, Item> for SlabSlab<Item>
28where
29 Item: core::fmt::Debug + Clone,
30{
31 type Error = SlabbableError;
32 fn with_fixed_capacity(cap: usize) -> Result<Self, Self::Error> {
34 Ok(Self {
35 inner: Slab::with_capacity(cap),
36 })
37 }
38 #[inline]
40 fn reserve_next(&mut self) -> Result<ReservedSlot, Self::Error> {
41 if self.inner.capacity() < self.inner.len() + 1 {
43 return Err(SlabbableError::AtCapacity(self.inner.capacity()));
44 }
45 let ins = self.inner.insert(ReserveStatus::Reserved);
46 Ok(ReservedSlot::issue(ins))
47 }
48 #[inline]
50 fn take_reserved_with(
51 &mut self,
52 r_slot: ReservedSlot,
53 with: Item,
54 ) -> Result<usize, Self::Error> {
55 let slot = r_slot.id();
56
57 let v = match self.inner.get_mut(slot) {
58 Some(v) => match v {
59 ReserveStatus::Reserved => v,
60 _ => return Err(SlabbableError::InvalidIndex(slot)),
61 },
62 _ => return Err(SlabbableError::InvalidIndex(slot)),
63 };
64 *v = ReserveStatus::Taken(with);
65 Ok(slot)
66 }
67 #[inline]
69 fn take_next_with(&mut self, with: Item) -> Result<usize, Self::Error> {
70 let reserved_slot = self.reserve_next()?;
71 self.take_reserved_with(reserved_slot, with)
72 }
73 #[inline]
75 fn mark_for_reuse(&mut self, slot: usize) -> Result<Item, Self::Error> {
76 if slot > self.inner.capacity() {
77 return Err(SlabbableError::InvalidIndex(slot));
78 }
79 match self.inner.try_remove(slot) {
80 Some(ReserveStatus::Taken(i)) => Ok(i),
81 _ => Err(SlabbableError::InvalidIndex(slot)),
82 }
83 }
84 #[inline]
86 fn slot_get_ref(&self, slot: usize) -> Result<Option<&Item>, Self::Error> {
87 if slot > self.inner.capacity() {
88 return Err(SlabbableError::InvalidIndex(slot));
89 }
90 match self.inner.get(slot) {
91 Some(ReserveStatus::Taken(itm_ref)) => Ok(Some(itm_ref)),
92 _ => Err(SlabbableError::InvalidIndex(slot)),
93 }
94 }
95 #[inline]
97 fn slot_get_mut(&mut self, slot: usize) -> Result<Option<&mut Item>, Self::Error> {
98 if slot > self.inner.capacity() {
99 return Err(SlabbableError::InvalidIndex(slot));
100 }
101 match self.inner.get_mut(slot) {
102 Some(ReserveStatus::Taken(itm_ref)) => Ok(Some(itm_ref)),
103 _ => Err(SlabbableError::InvalidIndex(slot)),
104 }
105 }
106 #[inline]
108 fn capacity(&self) -> usize {
109 self.inner.capacity()
110 }
111 #[inline]
113 fn remaining(&self) -> Option<usize> {
114 let rem = self.inner.capacity() - self.inner.len();
115 match rem {
116 0 => None,
117 1_usize.. => Some(rem),
118 }
119 }
120 fn reap(&mut self) -> Option<usize> {
122 None
124 }
125}