use crate::{
Extern, error::InstantiationError, exports::Exports, imports::Imports, module::Module,
store::AsStoreMut,
};
use wasmer_vm::{StoreHandle, VMInstance};
use super::store::Store;
#[derive(Clone, PartialEq, Eq)]
pub struct Instance {
_handle: StoreHandle<VMInstance>,
}
impl From<wasmer_compiler::InstantiationError> for InstantiationError {
fn from(other: wasmer_compiler::InstantiationError) -> Self {
match other {
wasmer_compiler::InstantiationError::Link(e) => Self::Link(e.into()),
wasmer_compiler::InstantiationError::Start(e) => Self::Start(e.into()),
wasmer_compiler::InstantiationError::CpuFeature(e) => Self::CpuFeature(e),
}
}
}
impl Instance {
#[allow(clippy::result_large_err)]
pub(crate) fn new(
store: &mut impl AsStoreMut,
module: &Module,
imports: &Imports,
) -> Result<(Self, Exports), InstantiationError> {
let externs = imports
.imports_for_module(module)
.map_err(InstantiationError::Link)?;
let mut handle = module.as_sys().instantiate(store, &externs)?;
let exports = Self::get_exports(store, module, handle.as_sys_mut());
let instance = Self {
_handle: StoreHandle::new(store.objects_mut().as_sys_mut(), handle.into_sys()),
};
Ok((instance, exports))
}
#[allow(clippy::result_large_err)]
pub(crate) fn new_by_index(
store: &mut impl AsStoreMut,
module: &Module,
externs: &[Extern],
) -> Result<(Self, Exports), InstantiationError> {
let externs = externs.to_vec();
let mut handle = module.as_sys().instantiate(store, &externs)?;
let exports = Self::get_exports(store, module, handle.as_sys_mut());
let instance = Self {
_handle: StoreHandle::new(
store.as_store_mut().objects_mut().as_sys_mut(),
handle.into_sys(),
),
};
Ok((instance, exports))
}
fn get_exports(
store: &mut impl AsStoreMut,
module: &Module,
handle: &mut VMInstance,
) -> Exports {
module
.exports()
.map(|export| {
let name = export.name().to_string();
let export = handle.lookup(&name).expect("export");
let extern_ = Extern::from_vm_extern(store, crate::vm::VMExtern::Sys(export));
(name, extern_)
})
.collect::<Exports>()
}
}
impl crate::BackendInstance {
pub(crate) fn into_sys(self) -> crate::backend::sys::instance::Instance {
match self {
Self::Sys(s) => s,
_ => panic!("Not a `sys` instance"),
}
}
}
#[cfg(test)]
mod send_test {
use super::*;
#[allow(dead_code)]
fn instance_is_send(inst: Instance) {
fn is_send(t: impl Send) {
let _ = t;
}
is_send(inst);
}
}