#[cfg(feature = "js")]
use crate::js::externals::table as table_impl;
#[cfg(feature = "jsc")]
use crate::jsc::externals::table as table_impl;
#[cfg(feature = "sys")]
use crate::sys::externals::table as table_impl;
use crate::exports::{ExportError, Exportable};
use crate::store::{AsStoreMut, AsStoreRef};
use crate::vm::{VMExtern, VMExternTable};
use crate::Extern;
use crate::RuntimeError;
use crate::TableType;
use crate::Value;
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "artifact-size", derive(loupe::MemoryUsage))]
pub struct Table(pub(crate) table_impl::Table);
impl Table {
pub fn new(
store: &mut impl AsStoreMut,
ty: TableType,
init: Value,
) -> Result<Self, RuntimeError> {
Ok(Self(table_impl::Table::new(store, ty, init)?))
}
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> {
table_impl::Table::copy(store, &dst_table.0, dst_index, &src_table.0, src_index, len)
}
pub(crate) fn from_vm_extern(store: &mut impl AsStoreMut, extern_: VMExternTable) -> Self {
Self(table_impl::Table::from_vm_extern(store, extern_))
}
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 std::cmp::Eq for Table {}
impl<'a> Exportable<'a> for Table {
fn get_self_from_extern(_extern: &'a Extern) -> Result<&'a Self, ExportError> {
match _extern {
Extern::Table(table) => Ok(table),
_ => Err(ExportError::IncompatibleType),
}
}
}
#[test]
fn test_table_grow_issue_3197() {
use crate::{imports, Instance, Module, Store, Table, TableType, Type, Value};
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();
}