wai_bindgen_wasmer/
table.rs1use std::convert::TryFrom;
2use std::fmt;
3use std::mem;
4
5pub struct Table<T> {
6 elems: Vec<Slot<T>>,
7 next: usize,
8}
9
10#[derive(Debug)]
11pub enum RemoveError {
12 NotAllocated,
13}
14
15enum Slot<T> {
16 Empty { next_empty: usize },
17 Full { item: Box<T> },
18}
19
20impl<T> Table<T> {
21 pub fn new() -> Table<T> {
23 Table {
24 elems: Vec::new(),
25 next: 0,
26 }
27 }
28
29 pub fn insert(&mut self, item: T) -> u32 {
32 if self.next == self.elems.len() {
33 let next_empty = self.next + 1;
34 self.elems.push(Slot::Empty { next_empty });
35 }
36 let index = self.next;
37 let ret = u32::try_from(index).unwrap();
38 self.next = match &self.elems[index] {
39 Slot::Empty { next_empty } => *next_empty,
40 Slot::Full { .. } => unreachable!(),
41 };
42 self.elems[index] = Slot::Full {
43 item: Box::new(item),
44 };
45 ret
46 }
47
48 pub fn get(&self, item: u32) -> Option<&T> {
53 let index = usize::try_from(item).unwrap();
54 match self.elems.get(index)? {
55 Slot::Empty { .. } => None,
56 Slot::Full { item } => Some(item),
57 }
58 }
59
60 pub fn remove(&mut self, item: u32) -> Result<T, RemoveError> {
64 let index = usize::try_from(item).unwrap();
65 let new_empty = Slot::Empty {
66 next_empty: self.next,
67 };
68 let slot = self.elems.get_mut(index).ok_or(RemoveError::NotAllocated)?;
69
70 match mem::replace(slot, new_empty) {
72 Slot::Full { item } => {
73 self.next = index;
74 Ok(*item)
75 }
76
77 Slot::Empty { next_empty } => {
80 *slot = Slot::Empty { next_empty };
81 Err(RemoveError::NotAllocated)
82 }
83 }
84 }
85}
86
87impl<T> Default for Table<T> {
88 fn default() -> Table<T> {
89 Table::new()
90 }
91}
92
93impl<T> fmt::Debug for Table<T> {
94 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
95 f.debug_struct("Table")
96 .field("capacity", &self.elems.capacity())
97 .finish()
98 }
99}
100
101impl fmt::Display for RemoveError {
102 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
103 match self {
104 RemoveError::NotAllocated => f.write_str("invalid handle index"),
105 }
106 }
107}
108
109impl std::error::Error for RemoveError {}
110
111#[cfg(test)]
112mod tests {
113 use super::*;
114
115 #[test]
116 fn simple() {
117 let mut table = Table::new();
118 assert_eq!(table.insert(0), 0);
119 assert_eq!(table.insert(100), 1);
120 assert_eq!(table.insert(200), 2);
121
122 assert_eq!(*table.get(0).unwrap(), 0);
123 assert_eq!(*table.get(1).unwrap(), 100);
124 assert_eq!(*table.get(2).unwrap(), 200);
125 assert!(table.get(100).is_none());
126
127 assert!(table.remove(0).is_ok());
128 assert!(table.get(0).is_none());
129 assert_eq!(table.insert(1), 0);
130 assert!(table.get(0).is_some());
131
132 table.get(1).unwrap();
133 assert!(table.remove(1).is_ok());
134 assert!(table.remove(1).is_err());
135
136 assert!(table.remove(2).is_ok());
137 assert!(table.remove(0).is_ok());
138
139 assert_eq!(table.insert(100), 0);
140 assert_eq!(table.insert(100), 2);
141 assert_eq!(table.insert(100), 1);
142 assert_eq!(table.insert(100), 3);
143 }
144}