rune/compile/v1/
slab.rs
1use core::mem::replace;
2
3use crate::alloc::{self, Vec};
4
5enum Entry<T> {
6 Vacant(usize),
7 Occupied(T),
8}
9
10pub(super) struct Slab<T> {
11 entries: Vec<Entry<T>>,
13
14 len: usize,
16
17 next: usize,
20}
21
22impl<T> Slab<T> {
23 pub(super) const fn new() -> Self {
24 Self {
25 entries: Vec::new(),
26 next: 0,
27 len: 0,
28 }
29 }
30
31 #[inline]
32 #[allow(unused)]
33 pub(super) fn len(&self) -> usize {
34 self.len
35 }
36
37 pub(super) fn insert(&mut self, val: T) -> alloc::Result<usize> {
38 let key = self.next;
39 self.insert_at(key, val)?;
40 Ok(key)
41 }
42
43 pub(super) fn try_remove(&mut self, key: usize) -> Option<T> {
44 if let Some(entry) = self.entries.get_mut(key) {
45 let prev = replace(entry, Entry::Vacant(self.next));
46
47 match prev {
48 Entry::Occupied(val) => {
49 self.len -= 1;
50 self.next = key;
51 return val.into();
52 }
53 _ => {
54 *entry = prev;
55 }
56 }
57 }
58
59 None
60 }
61
62 pub(super) fn get(&self, key: usize) -> Option<&T> {
63 match self.entries.get(key) {
64 Some(Entry::Occupied(ref val)) => Some(val),
65 _ => None,
66 }
67 }
68
69 pub(super) fn get_mut(&mut self, key: usize) -> Option<&mut T> {
70 match self.entries.get_mut(key) {
71 Some(&mut Entry::Occupied(ref mut val)) => Some(val),
72 _ => None,
73 }
74 }
75
76 pub(super) fn vacant_key(&self) -> usize {
77 self.next
78 }
79
80 fn insert_at(&mut self, key: usize, val: T) -> alloc::Result<()> {
81 self.len += 1;
82
83 if key == self.entries.len() {
84 self.entries.try_push(Entry::Occupied(val))?;
85 self.next = key + 1;
86 } else {
87 self.next = match self.entries.get(key) {
88 Some(&Entry::Vacant(next)) => next,
89 _ => unreachable!(),
90 };
91 self.entries[key] = Entry::Occupied(val);
92 }
93
94 Ok(())
95 }
96}