pawkit_holy_array/
lib.rs

1use std::{iter::FilterMap, slice::Iter};
2
3/// An array that allows holes in data, and automatically manages free slots
4#[derive(Debug)]
5pub struct HolyArray<T> {
6    data: Vec<Option<T>>,
7    free_slots: Vec<usize>,
8}
9
10impl<T> HolyArray<T> {
11    pub fn new() -> Self {
12        return Self {
13            data: vec![],
14            free_slots: vec![],
15        };
16    }
17
18    pub fn acquire(&mut self, value: T) -> usize {
19        let Some(idx) = self.free_slots.pop() else {
20            let idx = self.data.len();
21            self.data.push(Some(value));
22            return idx;
23        };
24
25        self.data[idx] = Some(value);
26
27        return idx;
28    }
29
30    pub fn release(&mut self, index: usize) {
31        if index >= self.data.len() {
32            return;
33        }
34
35        if self.data[index].is_none() {
36            return;
37        }
38
39        self.data[index] = None;
40        self.free_slots.push(index);
41    }
42
43    pub fn get(&self, index: usize) -> Option<&T> {
44        let Some(Some(value)) = self.data.get(index) else {
45            return None;
46        };
47
48        return Some(value);
49    }
50
51    pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
52        let Some(Some(value)) = self.data.get_mut(index) else {
53            return None;
54        };
55
56        return Some(value);
57    }
58
59    pub fn len(&self) -> usize {
60        return self.data.len();
61    }
62}
63
64impl<'a, T> IntoIterator for &'a HolyArray<T> {
65    type Item = &'a T;
66    type IntoIter = FilterMap<Iter<'a, Option<T>>, fn(&'a Option<T>) -> Option<&'a T>>;
67
68    fn into_iter(self) -> Self::IntoIter {
69        self.data.iter().filter_map(|item| item.as_ref())
70    }
71}