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