1use alloc::collections::BTreeMap;
15use alloc::vec::Vec;
16
17use crate::runtime::Value;
18use crate::types::TableType;
19
20const DENSE_LIMIT: u32 = 1 << 20; #[derive(Debug, Clone)]
26pub struct Table {
27 ty: TableType,
28 default: Value,
29 storage: TableStorage,
30}
31
32#[derive(Debug, Clone)]
33enum TableStorage {
34 Dense(Vec<Value>),
35 Sparse {
36 len: u32,
37 elems: BTreeMap<u32, Value>,
38 },
39}
40
41impl Table {
42 pub fn new(ty: TableType, default: Value) -> Option<Self> {
46 let min = ty.limits.min;
47 let storage = if min <= DENSE_LIMIT {
48 let mut vec = Vec::new();
49 vec.try_reserve(min as usize).ok()?;
50 vec.resize(min as usize, default);
51 TableStorage::Dense(vec)
52 } else {
53 TableStorage::Sparse {
54 len: min,
55 elems: BTreeMap::new(),
56 }
57 };
58 Some(Self {
59 ty,
60 default,
61 storage,
62 })
63 }
64
65 pub fn ty(&self) -> &TableType {
67 &self.ty
68 }
69
70 pub fn len(&self) -> u32 {
72 match &self.storage {
73 TableStorage::Dense(vec) => vec.len() as u32,
74 TableStorage::Sparse { len, .. } => *len,
75 }
76 }
77
78 pub fn is_empty(&self) -> bool {
80 self.len() == 0
81 }
82
83 pub fn get(&self, idx: u32) -> Option<Value> {
85 match &self.storage {
86 TableStorage::Dense(vec) => vec.get(idx as usize).copied(),
87 TableStorage::Sparse { len, elems } => {
88 if idx < *len {
89 Some(elems.get(&idx).copied().unwrap_or(self.default))
90 } else {
91 None
92 }
93 }
94 }
95 }
96
97 pub fn set(&mut self, idx: u32, value: Value) -> bool {
99 match &mut self.storage {
100 TableStorage::Dense(vec) => {
101 let Some(slot) = vec.get_mut(idx as usize) else {
102 return false;
103 };
104 *slot = value;
105 }
106 TableStorage::Sparse { len, elems } => {
107 if idx >= *len {
108 return false;
109 }
110 if value == self.default {
111 elems.remove(&idx);
112 } else {
113 elems.insert(idx, value);
114 }
115 }
116 }
117 true
118 }
119
120 pub fn grow(&mut self, delta: u32, fill: Value) -> Option<u32> {
123 let old = self.len();
124 let new = old.checked_add(delta)?;
125 if let Some(max) = self.ty.limits.max
126 && new > max
127 {
128 return None;
129 }
130 match &mut self.storage {
131 TableStorage::Dense(vec) => {
132 if new <= DENSE_LIMIT {
133 let additional = (new - old) as usize;
134 if vec.try_reserve(additional).is_err() {
135 return None;
136 }
137 vec.resize(new as usize, fill);
138 } else {
139 let mut elems = BTreeMap::new();
141 for (idx, value) in vec.iter().enumerate() {
142 if *value != self.default {
143 elems.insert(idx as u32, *value);
144 }
145 }
146 if fill != self.default {
147 for idx in old..new {
148 elems.insert(idx, fill);
149 }
150 }
151 self.storage = TableStorage::Sparse { len: new, elems };
152 }
153 }
154 TableStorage::Sparse { len, elems } => {
155 if fill != self.default {
156 for idx in old..new {
157 elems.insert(idx, fill);
158 }
159 }
160 *len = new;
161 }
162 }
163 Some(old)
164 }
165
166 pub fn fill(&mut self, start: u32, value: Value, count: u32) -> bool {
169 let Some(end) = start.checked_add(count) else {
170 return false;
171 };
172 match &mut self.storage {
173 TableStorage::Dense(vec) => {
174 if end as usize > vec.len() {
175 return false;
176 }
177 vec[start as usize..end as usize].fill(value);
178 }
179 TableStorage::Sparse { len, elems } => {
180 if end > *len {
181 return false;
182 }
183 if value == self.default {
184 for idx in start..end {
185 elems.remove(&idx);
186 }
187 } else {
188 for idx in start..end {
189 elems.insert(idx, value);
190 }
191 }
192 }
193 }
194 true
195 }
196
197 pub fn read_slice(&self, start: u32, count: u32) -> Option<Vec<Value>> {
199 let end = start.checked_add(count)?;
200 match &self.storage {
201 TableStorage::Dense(vec) => {
202 if end as usize > vec.len() {
203 return None;
204 }
205 Some(vec[start as usize..end as usize].to_vec())
206 }
207 TableStorage::Sparse { len, elems } => {
208 if end > *len {
209 return None;
210 }
211 let mut out = Vec::with_capacity(count as usize);
212 for idx in start..end {
213 out.push(elems.get(&idx).copied().unwrap_or(self.default));
214 }
215 Some(out)
216 }
217 }
218 }
219
220 pub fn write_slice(&mut self, start: u32, values: &[Value]) -> bool {
222 let Some(end) = start.checked_add(values.len() as u32) else {
223 return false;
224 };
225 match &mut self.storage {
226 TableStorage::Dense(vec) => {
227 if end as usize > vec.len() {
228 return false;
229 }
230 vec[start as usize..end as usize].copy_from_slice(values);
231 }
232 TableStorage::Sparse { len, elems } => {
233 if end > *len {
234 return false;
235 }
236 for (offset, value) in values.iter().enumerate() {
237 let idx = start + offset as u32;
238 if *value == self.default {
239 elems.remove(&idx);
240 } else {
241 elems.insert(idx, *value);
242 }
243 }
244 }
245 }
246 true
247 }
248}
249
250#[cfg(test)]
251mod tests {
252 use alloc::vec;
253
254 use super::*;
255 use crate::types::{Limits, RefType};
256
257 fn funcref_table(min: u32, max: Option<u32>) -> TableType {
258 TableType {
259 elem: RefType::FuncRef,
260 limits: Limits { min, max },
261 init: None,
262 }
263 }
264
265 #[test]
266 fn dense_roundtrip_and_grow() {
267 let mut table = Table::new(funcref_table(2, Some(8)), Value::FuncRef(None)).unwrap();
268 assert_eq!(table.len(), 2);
269 assert_eq!(table.get(0), Some(Value::FuncRef(None)));
270 assert!(table.set(1, Value::FuncRef(Some((0, 3)))));
271 assert_eq!(table.get(1), Some(Value::FuncRef(Some((0, 3)))));
272 assert!(!table.set(2, Value::FuncRef(None)));
273
274 assert_eq!(table.grow(2, Value::FuncRef(Some((1, 1)))), Some(2));
275 assert_eq!(table.len(), 4);
276 assert_eq!(table.get(3), Some(Value::FuncRef(Some((1, 1)))));
277 assert_eq!(table.grow(9, Value::FuncRef(None)), None);
279 }
280
281 #[test]
282 fn huge_table_is_sparse_and_usable() {
283 let mut table = Table::new(funcref_table(u32::MAX, None), Value::FuncRef(None)).unwrap();
285 assert_eq!(table.len(), u32::MAX);
286 assert_eq!(table.get(4_000_000_000), Some(Value::FuncRef(None)));
287 assert!(table.set(4_000_000_000, Value::FuncRef(Some((2, 5)))));
288 assert_eq!(table.get(4_000_000_000), Some(Value::FuncRef(Some((2, 5)))));
289 assert!(table.set(4_000_000_000, Value::FuncRef(None)));
291 assert_eq!(table.get(4_000_000_000), Some(Value::FuncRef(None)));
292 }
293
294 #[test]
295 fn grow_past_dense_limit_migrates() {
296 let mut table = Table::new(funcref_table(4, None), Value::FuncRef(None)).unwrap();
297 assert!(table.set(2, Value::FuncRef(Some((7, 7)))));
298 let old = table.grow(DENSE_LIMIT, Value::FuncRef(None)).unwrap();
299 assert_eq!(old, 4);
300 assert!(matches!(table.storage, TableStorage::Sparse { .. }));
301 assert_eq!(table.get(2), Some(Value::FuncRef(Some((7, 7)))));
303 assert_eq!(table.get(DENSE_LIMIT), Some(Value::FuncRef(None)));
304 }
305
306 #[test]
307 fn fill_and_slices() {
308 let mut table = Table::new(funcref_table(4, None), Value::FuncRef(None)).unwrap();
309 assert!(table.fill(1, Value::FuncRef(Some((0, 1))), 2));
310 assert_eq!(
311 table.read_slice(0, 4).unwrap(),
312 vec![
313 Value::FuncRef(None),
314 Value::FuncRef(Some((0, 1))),
315 Value::FuncRef(Some((0, 1))),
316 Value::FuncRef(None),
317 ]
318 );
319 assert!(table.write_slice(2, &[Value::FuncRef(Some((9, 9))), Value::FuncRef(None)]));
320 assert_eq!(table.get(2), Some(Value::FuncRef(Some((9, 9)))));
321 assert_eq!(table.get(3), Some(Value::FuncRef(None)));
322 assert!(!table.fill(3, Value::FuncRef(None), 2));
323 assert!(table.read_slice(3, 2).is_none());
324 assert!(!table.write_slice(3, &[Value::FuncRef(None), Value::FuncRef(None)]));
325 }
326}