use crate::sys::exports::Exports;
use crate::sys::externals::Extern;
use crate::sys::imports::Imports;
use crate::sys::module::Module;
use crate::sys::{LinkError, RuntimeError};
use std::fmt;
use thiserror::Error;
use wasmer_vm::{InstanceHandle, StoreHandle};
use super::store::AsStoreMut;
#[derive(Clone)]
pub struct Instance {
_handle: StoreHandle<InstanceHandle>,
module: Module,
pub exports: Exports,
}
#[cfg(test)]
mod send_test {
use super::*;
fn is_send<T: Send>() -> bool {
true
}
#[test]
fn instance_is_send() {
assert!(is_send::<Instance>());
}
}
#[derive(Error, Debug)]
pub enum InstantiationError {
#[error(transparent)]
Link(LinkError),
#[error(transparent)]
Start(RuntimeError),
#[error("missing required CPU features: {0:?}")]
CpuFeature(String),
#[error("cannot mix imports from different stores")]
DifferentStores,
}
impl From<wasmer_compiler::InstantiationError> for InstantiationError {
fn from(other: wasmer_compiler::InstantiationError) -> Self {
match other {
wasmer_compiler::InstantiationError::Link(e) => Self::Link(e),
wasmer_compiler::InstantiationError::Start(e) => Self::Start(e),
wasmer_compiler::InstantiationError::CpuFeature(e) => Self::CpuFeature(e),
}
}
}
impl Instance {
pub fn new(
store: &mut impl AsStoreMut,
module: &Module,
imports: &Imports,
) -> Result<Self, InstantiationError> {
let imports = imports
.imports_for_module(module)
.map_err(InstantiationError::Link)?;
let mut handle = module.instantiate(store, &imports)?;
let 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, export);
(name, extern_)
})
.collect::<Exports>();
let instance = Self {
_handle: StoreHandle::new(store.objects_mut(), handle),
module: module.clone(),
exports,
};
Ok(instance)
}
pub fn new_by_index(
store: &mut impl AsStoreMut,
module: &Module,
externs: &[Extern],
) -> Result<Self, InstantiationError> {
let imports = externs.to_vec();
let mut handle = module.instantiate(store, &imports)?;
let 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, export);
(name, extern_)
})
.collect::<Exports>();
let instance = Self {
_handle: StoreHandle::new(store.objects_mut(), handle),
module: module.clone(),
exports,
};
Ok(instance)
}
pub fn module(&self) -> &Module {
&self.module
}
}
impl fmt::Debug for Instance {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Instance")
.field("exports", &self.exports)
.finish()
}
}