1#![warn(missing_docs)]
13
14mod controller;
15pub mod error;
16pub mod iter;
17mod slot;
18
19#[cfg(test)]
20mod test;
21
22pub use controller::Controller;
23
24use error::{ArenaFull, InsertWithKeyError};
25use iter::{DrainFilter, Iter, IterMut};
26use slot::{ArenaSlot, ArenaSlotState};
27
28#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
30pub struct Key {
31 index: usize,
32 generation: usize,
33}
34
35#[derive(Debug)]
37pub struct Arena<T> {
38 controller: Controller,
39 slots: Vec<ArenaSlot<T>>,
40 first_occupied_slot_index: Option<usize>,
41}
42
43impl<T> Arena<T> {
44 pub fn new(capacity: usize) -> Self {
47 Self {
48 controller: Controller::new(capacity),
49 slots: (0..capacity).map(|_| ArenaSlot::new()).collect(),
50 first_occupied_slot_index: None,
51 }
52 }
53
54 pub fn controller(&self) -> Controller {
56 self.controller.clone()
57 }
58
59 pub fn capacity(&self) -> usize {
61 self.slots.len()
62 }
63
64 pub fn len(&self) -> usize {
66 self.slots
67 .iter()
68 .filter(|slot| matches!(&slot.state, ArenaSlotState::Occupied { .. }))
69 .count()
70 }
71
72 pub fn is_empty(&self) -> bool {
74 self.len() == 0
75 }
76
77 pub fn insert_with_key(&mut self, key: Key, data: T) -> Result<(), InsertWithKeyError> {
80 if let Some(slot) = self.slots.get(key.index) {
82 if slot.generation != key.generation {
83 return Err(InsertWithKeyError::InvalidKey);
84 }
85 if let ArenaSlotState::Occupied { .. } = &slot.state {
86 return Err(InsertWithKeyError::KeyNotReserved);
87 }
88 } else {
89 return Err(InsertWithKeyError::InvalidKey);
90 }
91
92 if let Some(head_index) = self.first_occupied_slot_index {
95 self.slots[head_index].set_previous_occupied_slot_index(Some(key.index));
96 }
97
98 self.slots[key.index].state = ArenaSlotState::Occupied {
100 data,
101 previous_occupied_slot_index: None,
102 next_occupied_slot_index: self.first_occupied_slot_index,
103 };
104
105 self.first_occupied_slot_index = Some(key.index);
107
108 Ok(())
109 }
110
111 pub fn insert(&mut self, data: T) -> Result<Key, ArenaFull> {
115 let key = self.controller.try_reserve()?;
116 self.insert_with_key(key, data).unwrap();
117 Ok(key)
118 }
119
120 fn remove_from_slot(&mut self, index: usize) -> Option<T> {
121 let slot = &mut self.slots[index];
122 let state = std::mem::replace(&mut slot.state, ArenaSlotState::Free);
123 match state {
124 ArenaSlotState::Free => None,
125 ArenaSlotState::Occupied {
126 data,
127 previous_occupied_slot_index,
128 next_occupied_slot_index,
129 } => {
130 slot.generation += 1;
131 self.controller.free(index);
132
133 if let Some(previous_index) = previous_occupied_slot_index {
135 self.slots[previous_index]
136 .set_next_occupied_slot_index(next_occupied_slot_index);
137 }
138 if let Some(next_index) = next_occupied_slot_index {
139 self.slots[next_index]
140 .set_previous_occupied_slot_index(previous_occupied_slot_index);
141 }
142
143 if self.first_occupied_slot_index.unwrap() == index {
150 self.first_occupied_slot_index = next_occupied_slot_index;
151 }
152
153 Some(data)
154 }
155 }
156 }
157
158 pub fn remove(&mut self, key: Key) -> Option<T> {
162 let slot = &mut self.slots[key.index];
170 if slot.generation != key.generation {
171 return None;
172 }
173 self.remove_from_slot(key.index)
174 }
175
176 pub fn get(&self, key: Key) -> Option<&T> {
179 let slot = &self.slots[key.index];
180 if slot.generation != key.generation {
181 return None;
182 }
183 match &slot.state {
184 ArenaSlotState::Free => None,
185 ArenaSlotState::Occupied { data, .. } => Some(data),
186 }
187 }
188
189 pub fn get_mut(&mut self, key: Key) -> Option<&mut T> {
192 let slot = &mut self.slots[key.index];
193 if slot.generation != key.generation {
194 return None;
195 }
196 match &mut slot.state {
197 ArenaSlotState::Free => None,
198 ArenaSlotState::Occupied { data, .. } => Some(data),
199 }
200 }
201
202 pub fn retain(&mut self, mut f: impl FnMut(&T) -> bool) {
206 let mut index = match self.first_occupied_slot_index {
207 Some(index) => index,
208 None => return,
209 };
210 loop {
211 if let ArenaSlotState::Occupied {
212 data,
213 next_occupied_slot_index,
214 ..
215 } = &self.slots[index].state
216 {
217 let next_occupied_slot_index = next_occupied_slot_index.as_ref().copied();
218 if !f(data) {
219 self.remove_from_slot(index);
220 }
221 index = match next_occupied_slot_index {
222 Some(index) => index,
223 None => return,
224 }
225 } else {
226 panic!("expected the slot pointed to by first_occupied_slot_index/next_occupied_slot_index to be occupied")
227 }
228 }
229 }
230
231 pub fn iter(&self) -> Iter<T> {
236 Iter::new(self)
237 }
238
239 pub fn iter_mut(&mut self) -> IterMut<T> {
244 IterMut::new(self)
245 }
246
247 pub fn drain_filter<F: FnMut(&T) -> bool>(&mut self, filter: F) -> DrainFilter<T, F> {
250 DrainFilter::new(self, filter)
251 }
252}
253
254impl<T> std::ops::Index<Key> for Arena<T> {
255 type Output = T;
256
257 fn index(&self, key: Key) -> &Self::Output {
258 self.get(key).expect("No item associated with this key")
259 }
260}
261
262impl<T> std::ops::IndexMut<Key> for Arena<T> {
263 fn index_mut(&mut self, key: Key) -> &mut Self::Output {
264 self.get_mut(key).expect("No item associated with this key")
265 }
266}
267
268impl<'a, T> IntoIterator for &'a Arena<T> {
269 type Item = (Key, &'a T);
270
271 type IntoIter = Iter<'a, T>;
272
273 fn into_iter(self) -> Self::IntoIter {
274 self.iter()
275 }
276}
277
278impl<'a, T> IntoIterator for &'a mut Arena<T> {
279 type Item = (Key, &'a mut T);
280
281 type IntoIter = IterMut<'a, T>;
282
283 fn into_iter(self) -> Self::IntoIter {
284 self.iter_mut()
285 }
286}