use wasmer_types::TableType;
pub(crate) mod inner;
pub(crate) use inner::*;
use crate::{
AsStoreMut, AsStoreRef, ExportError, Exportable, Extern, StoreMut, StoreRef, Value,
error::RuntimeError,
store::BackendStore,
vm::{VMExtern, VMExternTable},
};
#[derive(Debug, Clone, PartialEq, Eq, derive_more::From)]
#[cfg_attr(feature = "artifact-size", derive(loupe::MemoryUsage))]
pub struct Table(pub(crate) BackendTable);
impl Table {
pub fn new(
store: &mut impl AsStoreMut,
ty: TableType,
init: Value,
) -> Result<Self, RuntimeError> {
BackendTable::new(store, ty, init).map(Self)
}
pub fn ty(&self, store: &impl AsStoreRef) -> TableType {
self.0.ty(store)
}
pub fn get(&self, store: &mut impl AsStoreMut, index: u32) -> Option<Value> {
self.0.get(store, index)
}
pub fn set(
&self,
store: &mut impl AsStoreMut,
index: u32,
val: Value,
) -> Result<(), RuntimeError> {
self.0.set(store, index, val)
}
pub fn size(&self, store: &impl AsStoreRef) -> u32 {
self.0.size(store)
}
pub fn grow(
&self,
store: &mut impl AsStoreMut,
delta: u32,
init: Value,
) -> Result<u32, RuntimeError> {
self.0.grow(store, delta, init)
}
pub fn copy(
store: &mut impl AsStoreMut,
dst_table: &Self,
dst_index: u32,
src_table: &Self,
src_index: u32,
len: u32,
) -> Result<(), RuntimeError> {
BackendTable::copy(store, &dst_table.0, dst_index, &src_table.0, src_index, len)
}
pub(crate) fn from_vm_extern(store: &mut impl AsStoreMut, ext: VMExternTable) -> Self {
Self(BackendTable::from_vm_extern(store, ext))
}
pub fn is_from_store(&self, store: &impl AsStoreRef) -> bool {
self.0.is_from_store(store)
}
pub(crate) fn to_vm_extern(&self) -> VMExtern {
self.0.to_vm_extern()
}
}
impl<'a> Exportable<'a> for Table {
fn get_self_from_extern(ext: &'a Extern) -> Result<&'a Self, ExportError> {
match ext {
Extern::Table(table) => Ok(table),
_ => Err(ExportError::IncompatibleType),
}
}
}
#[cfg(test)]
mod test {
#[test]
#[cfg_attr(
feature = "wamr",
ignore = "wamr does not support direct calls to grow table"
)]
#[cfg_attr(feature = "wasmi", ignore = "wasmi does not support funcrefs")]
#[cfg_attr(
feature = "v8",
ignore = "growing tables in v8 is not currently supported"
)]
fn table_grow_issue_3197() {
use crate::{Instance, Module, Store, Table, TableType, Type, Value, imports};
const WAT: &str = r#"(module (table (import "env" "table") 100 funcref))"#;
let mut store = Store::default();
let module = Module::new(&store, WAT).unwrap();
let ty = TableType::new(Type::FuncRef, 0, None);
let table = Table::new(&mut store, ty, Value::FuncRef(None)).unwrap();
table.grow(&mut store, 100, Value::FuncRef(None)).unwrap();
assert_eq!(table.ty(&store).minimum, 0);
let imports = imports! {"env" => {"table" => table}};
let _instance = Instance::new(&mut store, &module, &imports).unwrap();
}
}