wasmer_runtime_core_fl/table/
mod.rs1use crate::{
4 error::CreationError,
5 export::Export,
6 import::IsExport,
7 types::{ElementType, TableDescriptor},
8 vm,
9};
10use std::{
11 convert::TryFrom,
12 fmt, ptr,
13 sync::{Arc, Mutex},
14};
15
16mod anyfunc;
17
18pub use self::anyfunc::Anyfunc;
19pub(crate) use self::anyfunc::AnyfuncTable;
20use crate::error::GrowError;
21
22#[derive(Debug, Clone, PartialEq, Eq)]
24pub enum TableAccessError {
25 IndexError,
27
28 #[allow(dead_code)]
30 TypeError,
32}
33
34pub trait StorableInTable: Sized {
36 fn unwrap_self(storage: &TableStorage, index: u32) -> Result<Self, TableAccessError>;
38
39 fn wrap_self(self, storage: &mut TableStorage, index: u32) -> Result<(), TableAccessError>;
41}
42
43impl<'a, F: Into<Anyfunc<'a>> + TryFrom<Anyfunc<'a>>> StorableInTable for F {
44 fn unwrap_self(storage: &TableStorage, index: u32) -> Result<Self, TableAccessError> {
45 match storage {
46 TableStorage::Anyfunc(ref anyfunc_table) => {
47 let anyfunc = anyfunc_table
48 .get(index)
49 .ok_or(TableAccessError::IndexError)?;
50 F::try_from(anyfunc).map_err(|_| TableAccessError::TypeError)
52 }
53 }
54 }
55
56 fn wrap_self(self, storage: &mut TableStorage, index: u32) -> Result<(), TableAccessError> {
57 let anyfunc: Anyfunc = self.into();
58
59 match storage {
60 TableStorage::Anyfunc(ref mut anyfunc_table) => anyfunc_table
61 .set(index, anyfunc)
62 .map_err(|_| TableAccessError::IndexError),
63 }
64 }
65}
66
67pub enum Element<'a> {
70 Anyfunc(Anyfunc<'a>),
72}
73
74impl<'a> StorableInTable for Element<'a> {
76 fn unwrap_self(storage: &TableStorage, index: u32) -> Result<Self, TableAccessError> {
77 match storage {
78 TableStorage::Anyfunc(ref anyfunc_table) => anyfunc_table
79 .get(index)
80 .map(Element::Anyfunc)
81 .ok_or(TableAccessError::IndexError),
82 }
83 }
84
85 fn wrap_self(self, storage: &mut TableStorage, index: u32) -> Result<(), TableAccessError> {
86 match self {
87 Element::Anyfunc(af) => af.wrap_self(storage, index),
88 }
89 }
90}
91
92pub enum TableStorage {
95 Anyfunc(Box<AnyfuncTable>),
97}
98
99pub struct Table {
101 desc: TableDescriptor,
102 storage: Arc<Mutex<(TableStorage, vm::LocalTable)>>,
103}
104
105impl Table {
106 pub fn new(desc: TableDescriptor) -> Result<Self, CreationError> {
128 if let Some(max) = desc.maximum {
129 if max < desc.minimum {
130 return Err(CreationError::InvalidDescriptor(
131 "Max table size is less than the minimum size".to_string(),
132 ));
133 }
134 }
135
136 let mut local = vm::LocalTable {
137 base: ptr::null_mut(),
138 count: 0,
139 table: ptr::null_mut(),
140 };
141
142 let storage = match desc.element {
143 ElementType::Anyfunc => TableStorage::Anyfunc(AnyfuncTable::new(desc, &mut local)?),
144 };
145
146 Ok(Self {
147 desc,
148 storage: Arc::new(Mutex::new((storage, local))),
149 })
150 }
151
152 pub fn descriptor(&self) -> TableDescriptor {
154 self.desc
155 }
156
157 #[allow(dead_code)]
160 pub(crate) fn get<T: StorableInTable>(&self, index: u32) -> Result<T, TableAccessError> {
163 let guard = self.storage.lock().unwrap();
164 let (storage, _) = &*guard;
165 T::unwrap_self(storage, index)
166 }
167
168 pub fn set<T: StorableInTable>(&self, index: u32, element: T) -> Result<(), TableAccessError> {
170 let mut guard = self.storage.lock().unwrap();
171 let (storage, _) = &mut *guard;
172 T::wrap_self(element, storage, index)
173 }
174
175 pub(crate) fn anyfunc_direct_access_mut<F, R>(&self, f: F) -> R
176 where
177 F: FnOnce(&mut [vm::Anyfunc]) -> R,
178 {
179 let mut storage = self.storage.lock().unwrap();
180 match &mut *storage {
181 (TableStorage::Anyfunc(ref mut anyfunc_table), _) => f(anyfunc_table.internal_buffer()),
182 }
183 }
184
185 pub fn size(&self) -> u32 {
187 let storage = self.storage.lock().unwrap();
188 match &*storage {
189 (TableStorage::Anyfunc(ref anyfunc_table), _) => anyfunc_table.current_size(),
190 }
191 }
192
193 pub fn grow(&self, delta: u32) -> Result<u32, GrowError> {
195 if delta == 0 {
196 return Ok(self.size());
197 }
198
199 let mut storage = self.storage.lock().unwrap();
200 match &mut *storage {
201 (TableStorage::Anyfunc(ref mut anyfunc_table), ref mut local) => anyfunc_table
202 .grow(delta, local)
203 .ok_or(GrowError::TableGrowError),
204 }
205 }
206
207 pub fn vm_local_table(&mut self) -> *mut vm::LocalTable {
209 let mut storage = self.storage.lock().unwrap();
210 &mut storage.1
211 }
212}
213
214impl IsExport for Table {
215 fn to_export(&self) -> Export {
216 Export::Table(self.clone())
217 }
218}
219
220impl Clone for Table {
221 fn clone(&self) -> Self {
222 Self {
223 desc: self.desc,
224 storage: Arc::clone(&self.storage),
225 }
226 }
227}
228
229impl fmt::Debug for Table {
230 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
231 f.debug_struct("Table")
232 .field("desc", &self.desc)
233 .field("size", &self.size())
234 .finish()
235 }
236}
237
238#[cfg(test)]
239mod table_tests {
240
241 use super::{ElementType, Table, TableDescriptor};
242
243 #[test]
244 fn test_initial_table_size() {
245 let table = Table::new(TableDescriptor {
246 element: ElementType::Anyfunc,
247 minimum: 10,
248 maximum: Some(20),
249 })
250 .unwrap();
251 assert_eq!(table.size(), 10);
252 }
253}