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> {
246 let slot = self.slots.get_mut(idx.slot as usize)?;
247 if slot.generation != idx.generation {
248 return None;
249 }
250 if matches!(slot.occupant, Occupant::Vacant { .. }) {
251 return None;
252 }
253
254 let vacated = Occupant::Vacant {
255 next_free: self.free_head,
256 };
257 let prior = core::mem::replace(&mut slot.occupant, vacated);
258 slot.generation = slot.generation.wrapping_add(1);
259 self.free_head = Some(idx.slot);
260 self.len -= 1;
261
262 match prior {
263 Occupant::Occupied(value) => Some(value),
264 Occupant::Vacant { .. } => None,
265 }
266 }
267
268 pub fn clear(&mut self) {
273 let total = self.slots.len();
274 for (i, slot) in self.slots.iter_mut().enumerate() {
275 if matches!(slot.occupant, Occupant::Occupied(_)) {
276 slot.generation = slot.generation.wrapping_add(1);
277 }
278 slot.occupant = Occupant::Vacant {
279 next_free: if i + 1 < total {
280 Some((i + 1) as u32)
281 } else {
282 None
283 },
284 };
285 }
286 self.free_head = if total == 0 { None } else { Some(0) };
287 self.len = 0;
288 }
289
290 #[inline]
310 pub fn iter(&self) -> Iter<'_, T> {
311 Iter {
312 slots: self.slots.iter().enumerate(),
313 }
314 }
315
316 #[inline]
318 pub fn iter_mut(&mut self) -> IterMut<'_, T> {
319 IterMut {
320 slots: self.slots.iter_mut().enumerate(),
321 }
322 }
323}
324
325impl<T> Default for Arena<T> {
326 #[inline]
327 fn default() -> Self {
328 Self::new()
329 }
330}
331
332impl<T: core::fmt::Debug> core::fmt::Debug for Arena<T> {
333 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
334 f.debug_struct("Arena")
335 .field("len", &self.len)
336 .field("capacity", &self.slots.capacity())
337 .finish()
338 }
339}
340
341pub struct Iter<'a, T> {
343 slots: core::iter::Enumerate<core::slice::Iter<'a, Slot<T>>>,
344}
345
346impl<'a, T> Iterator for Iter<'a, T> {
347 type Item = (Index, &'a T);
348
349 fn next(&mut self) -> Option<Self::Item> {
350 for (i, slot) in self.slots.by_ref() {
351 if let Occupant::Occupied(value) = &slot.occupant {
352 return Some((
353 Index {
354 generation: slot.generation,
355 slot: i as u32,
356 },
357 value,
358 ));
359 }
360 }
361 None
362 }
363}
364
365pub struct IterMut<'a, T> {
367 slots: core::iter::Enumerate<core::slice::IterMut<'a, Slot<T>>>,
368}
369
370impl<'a, T> Iterator for IterMut<'a, T> {
371 type Item = (Index, &'a mut T);
372
373 fn next(&mut self) -> Option<Self::Item> {
374 for (i, slot) in self.slots.by_ref() {
375 let generation = slot.generation;
376 if let Occupant::Occupied(value) = &mut slot.occupant {
377 return Some((
378 Index {
379 generation,
380 slot: i as u32,
381 },
382 value,
383 ));
384 }
385 }
386 None
387 }
388}
389
390#[cfg(test)]
391mod tests {
392 use super::*;
393
394 #[test]
395 fn insert_and_get() {
396 let mut a = Arena::new();
397 let i = a.insert(42);
398 assert_eq!(a.get(i), Some(&42));
399 assert_eq!(a.len(), 1);
400 assert!(!a.is_empty());
401 }
402
403 #[test]
404 fn remove_invalidates_handle() {
405 let mut a = Arena::new();
406 let i = a.insert("hello");
407 assert_eq!(a.remove(i), Some("hello"));
408 assert!(a.get(i).is_none());
409 assert!(a.remove(i).is_none());
410 }
411
412 #[test]
413 fn slot_reuse_bumps_generation() {
414 let mut a = Arena::new();
415 let i1 = a.insert(1);
416 let _ = a.remove(i1);
417 let i2 = a.insert(2);
418 assert_eq!(i1.slot(), i2.slot());
419 assert_ne!(i1.generation(), i2.generation());
420 assert!(a.get(i1).is_none());
421 assert_eq!(a.get(i2), Some(&2));
422 }
423
424 #[test]
425 fn iter_yields_only_live() {
426 let mut a = Arena::new();
427 let i1 = a.insert("a");
428 let i2 = a.insert("b");
429 let i3 = a.insert("c");
430 let _ = a.remove(i2);
431 let values: Vec<_> = a.iter().map(|(_, v)| *v).collect();
432 assert_eq!(values, vec!["a", "c"]);
433 let _ = (i1, i3);
434 }
435
436 #[test]
437 fn clear_resets_len_and_invalidates_handles() {
438 let mut a = Arena::new();
439 let i = a.insert(7);
440 a.clear();
441 assert_eq!(a.len(), 0);
442 assert!(a.get(i).is_none());
443 }
444
445 #[test]
446 fn get_mut_mutates() {
447 let mut a = Arena::new();
448 let i = a.insert(10);
449 if let Some(v) = a.get_mut(i) {
450 *v = 99;
451 }
452 assert_eq!(a.get(i), Some(&99));
453 }
454
455 #[test]
456 fn contains_reflects_liveness() {
457 let mut a = Arena::new();
458 let i = a.insert(0_u8);
459 assert!(a.contains(i));
460 let _ = a.remove(i);
461 assert!(!a.contains(i));
462 }
463}