1use alloc::vec::Vec;
16
17use crate::error::{Error, Result};
18
19#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
31pub struct Index {
32 generation: u32,
33 slot: u32,
34}
35
36impl Index {
37 #[inline]
42 pub const fn slot(self) -> u32 {
43 self.slot
44 }
45
46 #[inline]
48 pub const fn generation(self) -> u32 {
49 self.generation
50 }
51}
52
53enum Occupant<T> {
54 Occupied(T),
55 Vacant { next_free: Option<u32> },
56}
57
58struct Slot<T> {
59 generation: u32,
60 occupant: Occupant<T>,
61}
62
63pub struct Arena<T> {
83 slots: Vec<Slot<T>>,
84 free_head: Option<u32>,
85 len: usize,
86}
87
88impl<T> Arena<T> {
89 #[inline]
91 #[must_use]
92 pub const fn new() -> Self {
93 Self {
94 slots: Vec::new(),
95 free_head: None,
96 len: 0,
97 }
98 }
99
100 #[inline]
104 #[must_use]
105 pub fn with_capacity(capacity: usize) -> Self {
106 Self {
107 slots: Vec::with_capacity(capacity),
108 free_head: None,
109 len: 0,
110 }
111 }
112
113 #[inline]
115 pub fn reserve(&mut self, additional: usize) {
116 self.slots.reserve(additional);
117 }
118
119 #[inline]
121 #[must_use]
122 pub const fn len(&self) -> usize {
123 self.len
124 }
125
126 #[inline]
128 #[must_use]
129 pub const fn is_empty(&self) -> bool {
130 self.len == 0
131 }
132
133 #[inline]
137 #[must_use]
138 pub fn capacity(&self) -> usize {
139 self.slots.capacity()
140 }
141
142 #[inline]
144 #[must_use]
145 pub fn contains(&self, idx: Index) -> bool {
146 self.get(idx).is_some()
147 }
148
149 #[inline]
152 #[must_use]
153 pub fn get(&self, idx: Index) -> Option<&T> {
154 let slot = self.slots.get(idx.slot as usize)?;
155 if slot.generation != idx.generation {
156 return None;
157 }
158 match &slot.occupant {
159 Occupant::Occupied(value) => Some(value),
160 Occupant::Vacant { .. } => None,
161 }
162 }
163
164 #[inline]
167 #[must_use]
168 pub fn get_mut(&mut self, idx: Index) -> Option<&mut T> {
169 let slot = self.slots.get_mut(idx.slot as usize)?;
170 if slot.generation != idx.generation {
171 return None;
172 }
173 match &mut slot.occupant {
174 Occupant::Occupied(value) => Some(value),
175 Occupant::Vacant { .. } => None,
176 }
177 }
178
179 #[inline]
184 pub fn insert(&mut self, value: T) -> Index {
185 match self.try_insert(value) {
186 Ok(idx) => idx,
187 Err(_) => panic!("arena slot counter overflow (u32::MAX slots)"),
188 }
189 }
190
191 pub fn try_insert(&mut self, value: T) -> Result<Index> {
194 if let Some(slot_id) = self.free_head {
195 let slot = match self.slots.get_mut(slot_id as usize) {
196 Some(s) => s,
197 None => return Err(Error::CounterOverflow),
198 };
199 let next_free = match &slot.occupant {
200 Occupant::Vacant { next_free } => *next_free,
201 Occupant::Occupied(_) => return Err(Error::CounterOverflow),
202 };
203 self.free_head = next_free;
204 slot.occupant = Occupant::Occupied(value);
205 self.len += 1;
206 Ok(Index {
207 generation: slot.generation,
208 slot: slot_id,
209 })
210 } else {
211 let slot_idx = self.slots.len();
212 if slot_idx > u32::MAX as usize {
213 return Err(Error::CounterOverflow);
214 }
215 self.slots.push(Slot {
216 generation: 1,
217 occupant: Occupant::Occupied(value),
218 });
219 self.len += 1;
220 Ok(Index {
221 generation: 1,
222 slot: slot_idx as u32,
223 })
224 }
225 }
226
227 pub fn remove(&mut self, idx: Index) -> Option<T> {
230 let slot = self.slots.get_mut(idx.slot as usize)?;
231 if slot.generation != idx.generation {
232 return None;
233 }
234 if matches!(slot.occupant, Occupant::Vacant { .. }) {
235 return None;
236 }
237
238 let vacated = Occupant::Vacant {
239 next_free: self.free_head,
240 };
241 let prior = core::mem::replace(&mut slot.occupant, vacated);
242 slot.generation = slot.generation.wrapping_add(1);
243 self.free_head = Some(idx.slot);
244 self.len -= 1;
245
246 match prior {
247 Occupant::Occupied(value) => Some(value),
248 Occupant::Vacant { .. } => None,
249 }
250 }
251
252 pub fn clear(&mut self) {
257 let total = self.slots.len();
258 for (i, slot) in self.slots.iter_mut().enumerate() {
259 if matches!(slot.occupant, Occupant::Occupied(_)) {
260 slot.generation = slot.generation.wrapping_add(1);
261 }
262 slot.occupant = Occupant::Vacant {
263 next_free: if i + 1 < total {
264 Some((i + 1) as u32)
265 } else {
266 None
267 },
268 };
269 }
270 self.free_head = if total == 0 { None } else { Some(0) };
271 self.len = 0;
272 }
273
274 #[inline]
276 pub fn iter(&self) -> Iter<'_, T> {
277 Iter {
278 slots: self.slots.iter().enumerate(),
279 }
280 }
281
282 #[inline]
284 pub fn iter_mut(&mut self) -> IterMut<'_, T> {
285 IterMut {
286 slots: self.slots.iter_mut().enumerate(),
287 }
288 }
289}
290
291impl<T> Default for Arena<T> {
292 #[inline]
293 fn default() -> Self {
294 Self::new()
295 }
296}
297
298impl<T: core::fmt::Debug> core::fmt::Debug for Arena<T> {
299 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
300 f.debug_struct("Arena")
301 .field("len", &self.len)
302 .field("capacity", &self.slots.capacity())
303 .finish()
304 }
305}
306
307pub struct Iter<'a, T> {
309 slots: core::iter::Enumerate<core::slice::Iter<'a, Slot<T>>>,
310}
311
312impl<'a, T> Iterator for Iter<'a, T> {
313 type Item = (Index, &'a T);
314
315 fn next(&mut self) -> Option<Self::Item> {
316 for (i, slot) in self.slots.by_ref() {
317 if let Occupant::Occupied(value) = &slot.occupant {
318 return Some((
319 Index {
320 generation: slot.generation,
321 slot: i as u32,
322 },
323 value,
324 ));
325 }
326 }
327 None
328 }
329}
330
331pub struct IterMut<'a, T> {
333 slots: core::iter::Enumerate<core::slice::IterMut<'a, Slot<T>>>,
334}
335
336impl<'a, T> Iterator for IterMut<'a, T> {
337 type Item = (Index, &'a mut T);
338
339 fn next(&mut self) -> Option<Self::Item> {
340 for (i, slot) in self.slots.by_ref() {
341 let generation = slot.generation;
342 if let Occupant::Occupied(value) = &mut slot.occupant {
343 return Some((
344 Index {
345 generation,
346 slot: i as u32,
347 },
348 value,
349 ));
350 }
351 }
352 None
353 }
354}
355
356#[cfg(test)]
357mod tests {
358 use super::*;
359
360 #[test]
361 fn insert_and_get() {
362 let mut a = Arena::new();
363 let i = a.insert(42);
364 assert_eq!(a.get(i), Some(&42));
365 assert_eq!(a.len(), 1);
366 assert!(!a.is_empty());
367 }
368
369 #[test]
370 fn remove_invalidates_handle() {
371 let mut a = Arena::new();
372 let i = a.insert("hello");
373 assert_eq!(a.remove(i), Some("hello"));
374 assert!(a.get(i).is_none());
375 assert!(a.remove(i).is_none());
376 }
377
378 #[test]
379 fn slot_reuse_bumps_generation() {
380 let mut a = Arena::new();
381 let i1 = a.insert(1);
382 let _ = a.remove(i1);
383 let i2 = a.insert(2);
384 assert_eq!(i1.slot(), i2.slot());
385 assert_ne!(i1.generation(), i2.generation());
386 assert!(a.get(i1).is_none());
387 assert_eq!(a.get(i2), Some(&2));
388 }
389
390 #[test]
391 fn iter_yields_only_live() {
392 let mut a = Arena::new();
393 let i1 = a.insert("a");
394 let i2 = a.insert("b");
395 let i3 = a.insert("c");
396 let _ = a.remove(i2);
397 let values: Vec<_> = a.iter().map(|(_, v)| *v).collect();
398 assert_eq!(values, vec!["a", "c"]);
399 let _ = (i1, i3);
400 }
401
402 #[test]
403 fn clear_resets_len_and_invalidates_handles() {
404 let mut a = Arena::new();
405 let i = a.insert(7);
406 a.clear();
407 assert_eq!(a.len(), 0);
408 assert!(a.get(i).is_none());
409 }
410
411 #[test]
412 fn get_mut_mutates() {
413 let mut a = Arena::new();
414 let i = a.insert(10);
415 if let Some(v) = a.get_mut(i) {
416 *v = 99;
417 }
418 assert_eq!(a.get(i), Some(&99));
419 }
420
421 #[test]
422 fn contains_reflects_liveness() {
423 let mut a = Arena::new();
424 let i = a.insert(0_u8);
425 assert!(a.contains(i));
426 let _ = a.remove(i);
427 assert!(!a.contains(i));
428 }
429}