wasmedge_sys/instance/
table.rs1use crate::{
9 ffi::{self},
10 types::{WasmEdgeLimit, WasmValue},
11 utils::check,
12 WasmEdgeResult,
13};
14
15use wasmedge_types::{
16 error::{TableError, WasmEdgeError},
17 RefType, ValType,
18};
19
20#[derive(Debug)]
24pub struct Table {
25 pub(crate) inner: InnerTable,
26}
27impl Table {
28 pub fn create(ty: wasmedge_types::TableType) -> WasmEdgeResult<Self> {
38 let ty: TableType = ty.into();
39 let ctx = unsafe { ffi::WasmEdge_TableInstanceCreate(ty.inner.0) };
40
41 if ctx.is_null() {
42 Err(Box::new(WasmEdgeError::Table(TableError::Create)))
43 } else {
44 Ok(Table {
45 inner: InnerTable(ctx),
46 })
47 }
48 }
49
50 pub fn ty(&self) -> WasmEdgeResult<wasmedge_types::TableType> {
56 let ty_ctx = unsafe { ffi::WasmEdge_TableInstanceGetTableType(self.inner.0) };
57 if ty_ctx.is_null() {
58 Err(Box::new(WasmEdgeError::Table(TableError::Type)))
59 } else {
60 let ty = std::mem::ManuallyDrop::new(TableType {
61 inner: InnerTableType(ty_ctx as *mut _),
62 });
63 Ok((&*ty).into())
64 }
65 }
66
67 pub fn get_data(&self, idx: u32) -> WasmEdgeResult<WasmValue> {
77 let raw_val = unsafe {
78 let mut data = ffi::WasmEdge_ValueGenI32(0);
79 check(ffi::WasmEdge_TableInstanceGetData(
80 self.inner.0,
81 &mut data as *mut _,
82 idx.into(),
83 ))?;
84 data
85 };
86 Ok(raw_val.into())
87 }
88
89 pub fn set_data(&mut self, data: WasmValue, idx: u32) -> WasmEdgeResult<()> {
101 unsafe {
102 check(ffi::WasmEdge_TableInstanceSetData(
103 self.inner.0,
104 data.as_raw(),
105 idx.into(),
106 ))
107 }
108 }
109
110 pub fn capacity(&self) -> usize {
113 unsafe { ffi::WasmEdge_TableInstanceGetSize(self.inner.0) as usize }
114 }
115
116 pub fn grow(&mut self, size: u32) -> WasmEdgeResult<()> {
128 unsafe { check(ffi::WasmEdge_TableInstanceGrow(self.inner.0, size.into())) }
129 }
130
131 pub unsafe fn as_ptr(&self) -> *const ffi::WasmEdge_TableInstanceContext {
135 self.inner.0 as *const _
136 }
137
138 pub unsafe fn from_raw(ptr: *mut ffi::WasmEdge_TableInstanceContext) -> Self {
142 Self {
143 inner: InnerTable(ptr),
144 }
145 }
146}
147impl Drop for Table {
148 fn drop(&mut self) {
149 unsafe { ffi::WasmEdge_TableInstanceDelete(self.inner.0) };
150 }
151}
152
153#[derive(Debug)]
154pub(crate) struct InnerTable(pub(crate) *mut ffi::WasmEdge_TableInstanceContext);
155unsafe impl Send for InnerTable {}
156unsafe impl Sync for InnerTable {}
157
158#[derive(Debug)]
160pub(crate) struct TableType {
161 pub(crate) inner: InnerTableType,
162}
163impl Drop for TableType {
164 fn drop(&mut self) {
165 unsafe {
166 ffi::WasmEdge_TableTypeDelete(self.inner.0);
167 }
168 }
169}
170impl TableType {
171 pub(crate) fn create(elem_ty: RefType, min: u32, max: Option<u32>) -> WasmEdgeResult<Self> {
192 let ty: ValType = elem_ty.into();
193 let limit_ctx = WasmEdgeLimit::new(min, max, false).to_context();
196 let ctx = unsafe { ffi::WasmEdge_TableTypeCreate(ty.into(), limit_ctx) };
197 unsafe { ffi::WasmEdge_LimitDelete(limit_ctx) };
198 if ctx.is_null() {
199 Err(Box::new(WasmEdgeError::TableTypeCreate))
200 } else {
201 Ok(Self {
202 inner: InnerTableType(ctx),
203 })
204 }
205 }
206
207 pub(crate) fn elem_ty(&self) -> RefType {
209 let ty = unsafe { ffi::WasmEdge_TableTypeGetRefType(self.inner.0) };
210 let ty: ValType = ty.into();
211 ty.into()
212 }
213
214 pub(crate) fn min(&self) -> u32 {
216 let limit = unsafe { ffi::WasmEdge_TableTypeGetLimit(self.inner.0) };
217 let limit = WasmEdgeLimit::from_context(limit);
218 limit.min()
219 }
220
221 pub(crate) fn max(&self) -> Option<u32> {
223 let limit = unsafe { ffi::WasmEdge_TableTypeGetLimit(self.inner.0) };
224 let limit = WasmEdgeLimit::from_context(limit);
225 limit.max()
226 }
227}
228impl From<wasmedge_types::TableType> for TableType {
229 fn from(ty: wasmedge_types::TableType) -> Self {
230 TableType::create(ty.elem_ty(), ty.minimum(), ty.maximum()).expect(
231 "[wasmedge] Failed to convert wasmedge_types::TableType into wasmedge_sys::TableType.",
232 )
233 }
234}
235impl From<&TableType> for wasmedge_types::TableType {
236 fn from(ty: &TableType) -> Self {
237 wasmedge_types::TableType::new(ty.elem_ty(), ty.min(), ty.max())
238 }
239}
240
241#[derive(Debug)]
242pub(crate) struct InnerTableType(pub(crate) *mut ffi::WasmEdge_TableTypeContext);
243unsafe impl Send for InnerTableType {}
244unsafe impl Sync for InnerTableType {}
245
246#[cfg(test)]
247mod tests {
248 use super::*;
249 use crate::{instance::function::AsFunc, CallingFrame, Function, Instance};
250 use std::thread;
251 use wasmedge_types::{
252 error::{CoreError, CoreExecutionError},
253 RefType, ValType,
254 };
255
256 #[test]
257 #[allow(clippy::assertions_on_result_states)]
258 fn test_table_type() {
259 let result = TableType::create(RefType::FuncRef, 10, Some(20));
261 assert!(result.is_ok());
262 let ty = result.unwrap();
263 assert!(!ty.inner.0.is_null());
264
265 assert_eq!(ty.elem_ty(), RefType::FuncRef);
267 assert_eq!(ty.min(), 10);
269 assert_eq!(ty.max(), Some(20));
270 }
271
272 #[test]
273 #[allow(clippy::assertions_on_result_states)]
274 fn test_table() {
275 let ty = wasmedge_types::TableType::new(RefType::FuncRef, 10, Some(20));
277
278 let result = Table::create(ty);
280 assert!(result.is_ok());
281 let mut table = result.unwrap();
282
283 assert_eq!(table.capacity(), 10);
285
286 let result = table.ty();
288 assert!(result.is_ok());
289 let ty = result.unwrap();
290
291 assert_eq!(ty.minimum(), 10);
293 assert_eq!(ty.maximum(), Some(20));
294 assert_eq!(ty.elem_ty(), RefType::FuncRef);
295
296 let result = table.grow(5);
298 assert!(result.is_ok());
299 assert_eq!(table.capacity(), 15);
301 }
302
303 #[test]
304 #[allow(clippy::assertions_on_result_states)]
305 fn test_table_data() {
306 let func_ty = wasmedge_types::FuncType::new(vec![ValType::I32; 2], vec![ValType::I32]);
308 let mut host_data = ();
310 let result =
311 unsafe { Function::create_sync_func::<()>(&func_ty, real_add, &mut host_data, 0) };
312 assert!(result.is_ok());
313 let host_func = result.unwrap();
314
315 let ty = wasmedge_types::TableType::new(RefType::FuncRef, 10, Some(20));
317
318 let result = Table::create(ty);
320 assert!(result.is_ok());
321 let mut table = result.unwrap();
322
323 assert_eq!(table.capacity(), 10);
325
326 let result = table.get_data(9);
328 assert!(result.is_ok());
329 let value = result.unwrap();
330 assert!(value.is_null_ref());
331 assert_eq!(value.ty(), ValType::FuncRef);
332
333 let result = table.set_data(WasmValue::from_func_ref((&host_func).into()), 3);
335 assert!(result.is_ok());
336 let result = table.get_data(3);
338 assert!(result.is_ok());
339 let value = result.unwrap();
340 let result = value.func_ref();
341 assert!(result.is_some());
342 let func_ref = result.unwrap();
343
344 let result = func_ref.ty();
346 assert!(result.is_some());
347 let func_ty = result.unwrap();
348 assert_eq!(func_ty.args_len(), 2);
349 assert_eq!(func_ty.args(), &[ValType::I32, ValType::I32]);
350 assert_eq!(func_ty.returns_len(), 1);
351 assert_eq!(func_ty.returns(), &[ValType::I32]);
352 }
353
354 #[test]
355 fn test_table_send() {
356 let ty = wasmedge_types::TableType::new(RefType::FuncRef, 10, Some(20));
358
359 let result = Table::create(ty);
361 assert!(result.is_ok());
362 let table = result.unwrap();
363
364 let handle = thread::spawn(move || {
365 assert!(!table.inner.0.is_null());
366
367 assert_eq!(table.capacity(), 10);
369
370 let result = table.ty();
372 assert!(result.is_ok());
373 let ty = result.unwrap();
374
375 assert_eq!(ty.minimum(), 10);
377 assert_eq!(ty.maximum(), Some(20));
378 assert_eq!(ty.elem_ty(), RefType::FuncRef);
379 });
380
381 handle.join().unwrap();
382 }
383
384 #[test]
385 fn test_table_sync() {
386 let ty = wasmedge_types::TableType::new(RefType::FuncRef, 10, Some(20));
388
389 let result = Table::create(ty);
391
392 assert!(result.is_ok());
393 let table = result.unwrap();
394
395 let table = &table;
396
397 std::thread::scope(move |s| {
398 let _ = s
399 .spawn(|| {
400 let result = table.ty();
401 assert!(result.is_ok());
402 let ty = result.unwrap();
403 assert_eq!(ty.minimum(), 10);
405 assert_eq!(ty.maximum(), Some(20));
406 assert_eq!(ty.elem_ty(), RefType::FuncRef);
407 })
408 .join();
409 });
410 }
411
412 fn real_add(
413 _data: &mut (),
414 _inst: &mut Instance,
415 _frame: &mut CallingFrame,
416 input: Vec<WasmValue>,
417 ) -> Result<Vec<WasmValue>, CoreError> {
418 println!("Rust: Entering Rust function real_add");
419
420 if input.len() != 2 {
421 return Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch));
422 }
423
424 let a = if input[0].ty() == ValType::I32 {
425 input[0].to_i32()
426 } else {
427 return Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch));
428 };
429
430 let b = if input[1].ty() == ValType::I32 {
431 input[0].to_i32()
432 } else {
433 return Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch));
434 };
435
436 let c = a + b;
437 println!("Rust: calcuating in real_add c: {c:?}");
438
439 println!("Rust: Leaving Rust function real_add");
440 Ok(vec![WasmValue::from_i32(c)])
441 }
442}