pub(crate) use self::builder::InstanceEntityBuilder;
pub use self::exports::{Export, ExportsIter, Extern, ExternType};
use super::{
engine::DedupFuncType,
AsContext,
Func,
Global,
Memory,
Module,
StoreContext,
Stored,
Table,
};
use crate::{
collections::{arena::ArenaIndex, Map},
func::FuncError,
memory::DataSegment,
AsContextMut,
ElementSegment,
Error,
TypedFunc,
WasmParams,
WasmResults,
};
use alloc::{boxed::Box, sync::Arc};
mod builder;
mod exports;
#[cfg(test)]
mod tests;
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct InstanceIdx(u32);
impl ArenaIndex for InstanceIdx {
fn into_usize(self) -> usize {
self.0 as usize
}
fn from_usize(value: usize) -> Self {
let value = value.try_into().unwrap_or_else(|error| {
panic!("index {value} is out of bounds as instance index: {error}")
});
Self(value)
}
}
#[derive(Debug)]
pub struct InstanceEntity {
initialized: bool,
func_types: Arc<[DedupFuncType]>,
tables: Box<[Table]>,
funcs: Box<[Func]>,
memories: Box<[Memory]>,
globals: Box<[Global]>,
exports: Map<Box<str>, Extern>,
data_segments: Box<[DataSegment]>,
elem_segments: Box<[ElementSegment]>,
}
impl InstanceEntity {
pub fn uninitialized() -> InstanceEntity {
Self {
initialized: false,
func_types: Arc::new([]),
tables: [].into(),
funcs: [].into(),
memories: [].into(),
globals: [].into(),
exports: Map::new(),
data_segments: [].into(),
elem_segments: [].into(),
}
}
pub fn build(module: &Module) -> InstanceEntityBuilder {
InstanceEntityBuilder::new(module)
}
pub fn is_initialized(&self) -> bool {
self.initialized
}
pub fn get_memory(&self, index: u32) -> Option<Memory> {
self.memories.get(index as usize).copied()
}
pub fn get_table(&self, index: u32) -> Option<Table> {
self.tables.get(index as usize).copied()
}
pub fn get_global(&self, index: u32) -> Option<Global> {
self.globals.get(index as usize).copied()
}
pub fn get_func(&self, index: u32) -> Option<Func> {
self.funcs.get(index as usize).copied()
}
pub fn get_signature(&self, index: u32) -> Option<&DedupFuncType> {
self.func_types.get(index as usize)
}
pub fn get_data_segment(&self, index: u32) -> Option<DataSegment> {
self.data_segments.get(index as usize).copied()
}
pub fn get_element_segment(&self, index: u32) -> Option<ElementSegment> {
self.elem_segments.get(index as usize).copied()
}
pub fn get_export(&self, name: &str) -> Option<Extern> {
self.exports.get(name).copied()
}
pub fn exports(&self) -> ExportsIter<'_> {
ExportsIter::new(self.exports.iter())
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(transparent)]
pub struct Instance(Stored<InstanceIdx>);
impl Instance {
pub fn new(
mut store: impl AsContextMut,
module: &Module,
imports: &[Extern],
) -> Result<Instance, Error> {
let instance = Module::instantiate(module, &mut store, imports.iter().cloned())?;
Ok(instance)
}
pub(super) fn from_inner(stored: Stored<InstanceIdx>) -> Self {
Self(stored)
}
pub(super) fn as_inner(&self) -> &Stored<InstanceIdx> {
&self.0
}
pub(crate) fn get_func_by_index(&self, store: impl AsContext, index: u32) -> Option<Func> {
store
.as_context()
.store
.inner
.resolve_instance(self)
.get_func(index)
}
pub fn get_export(&self, store: impl AsContext, name: &str) -> Option<Extern> {
store
.as_context()
.store
.inner
.resolve_instance(self)
.get_export(name)
}
pub fn get_func(&self, store: impl AsContext, name: &str) -> Option<Func> {
self.get_export(store, name)?.into_func()
}
pub fn get_typed_func<Params, Results>(
&self,
store: impl AsContext,
name: &str,
) -> Result<TypedFunc<Params, Results>, Error>
where
Params: WasmParams,
Results: WasmResults,
{
self.get_export(&store, name)
.and_then(Extern::into_func)
.ok_or_else(|| Error::from(FuncError::ExportedFuncNotFound))?
.typed::<Params, Results>(store)
}
pub fn get_global(&self, store: impl AsContext, name: &str) -> Option<Global> {
self.get_export(store, name)?.into_global()
}
pub fn get_table(&self, store: impl AsContext, name: &str) -> Option<Table> {
self.get_export(store, name)?.into_table()
}
pub fn get_memory(&self, store: impl AsContext, name: &str) -> Option<Memory> {
self.get_export(store, name)?.into_memory()
}
pub fn exports<'ctx, T: 'ctx>(
&self,
store: impl Into<StoreContext<'ctx, T>>,
) -> ExportsIter<'ctx> {
store.into().store.inner.resolve_instance(self).exports()
}
}