use std::sync::Arc;
use crate::{ImportInitializerFuncPtr, VMExtern, VMFunction, VMGlobal, VMMemory, VMTable};
#[derive(Debug, Clone)]
pub enum Export {
Function(ExportFunction),
Table(VMTable),
Memory(VMMemory),
Global(VMGlobal),
}
impl From<Export> for VMExtern {
fn from(other: Export) -> Self {
match other {
Export::Function(ExportFunction { vm_function, .. }) => Self::Function(vm_function),
Export::Memory(vm_memory) => Self::Memory(vm_memory),
Export::Table(vm_table) => Self::Table(vm_table),
Export::Global(vm_global) => Self::Global(vm_global),
}
}
}
impl From<VMExtern> for Export {
fn from(other: VMExtern) -> Self {
match other {
VMExtern::Function(vm_function) => {
Self::Function(ExportFunction { vm_function, metadata: None })
}
VMExtern::Memory(vm_memory) => Self::Memory(vm_memory),
VMExtern::Table(vm_table) => Self::Table(vm_table),
VMExtern::Global(vm_global) => Self::Global(vm_global),
}
}
}
#[derive(Debug, PartialEq)]
pub struct ExportFunctionMetadata {
pub host_env: *mut std::ffi::c_void,
pub import_init_function_ptr: Option<ImportInitializerFuncPtr>,
pub host_env_clone_fn: fn(*mut std::ffi::c_void) -> *mut std::ffi::c_void,
pub host_env_drop_fn: unsafe fn(*mut std::ffi::c_void),
}
unsafe impl Send for ExportFunctionMetadata {}
unsafe impl Sync for ExportFunctionMetadata {}
impl ExportFunctionMetadata {
pub unsafe fn new(
host_env: *mut std::ffi::c_void,
import_init_function_ptr: Option<ImportInitializerFuncPtr>,
host_env_clone_fn: fn(*mut std::ffi::c_void) -> *mut std::ffi::c_void,
host_env_drop_fn: fn(*mut std::ffi::c_void),
) -> Self {
Self { host_env, import_init_function_ptr, host_env_clone_fn, host_env_drop_fn }
}
}
impl Drop for ExportFunctionMetadata {
fn drop(&mut self) {
if !self.host_env.is_null() {
unsafe {
(self.host_env_drop_fn)(self.host_env);
}
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct ExportFunction {
pub vm_function: VMFunction,
pub metadata: Option<Arc<ExportFunctionMetadata>>,
}
impl From<ExportFunction> for Export {
fn from(func: ExportFunction) -> Self {
Self::Function(func)
}
}
impl From<VMTable> for Export {
fn from(table: VMTable) -> Self {
Self::Table(table)
}
}
impl From<VMMemory> for Export {
fn from(memory: VMMemory) -> Self {
Self::Memory(memory)
}
}
impl From<VMGlobal> for Export {
fn from(global: VMGlobal) -> Self {
Self::Global(global)
}
}
pub trait Resolver {
fn resolve(&self, _index: u32, module: &str, field: &str) -> Option<Export>;
}
pub trait NamedResolver {
fn resolve_by_name(&self, module: &str, field: &str) -> Option<Export>;
}
impl<T: NamedResolver> Resolver for T {
fn resolve(&self, _index: u32, module: &str, field: &str) -> Option<Export> {
self.resolve_by_name(module, field)
}
}
impl<T: NamedResolver> NamedResolver for &T {
fn resolve_by_name(&self, module: &str, field: &str) -> Option<Export> {
(**self).resolve_by_name(module, field)
}
}
impl NamedResolver for Box<dyn NamedResolver + Send + Sync> {
fn resolve_by_name(&self, module: &str, field: &str) -> Option<Export> {
(**self).resolve_by_name(module, field)
}
}
impl NamedResolver for () {
fn resolve_by_name(&self, _module: &str, _field: &str) -> Option<Export> {
None
}
}
pub struct NullResolver {}
impl Resolver for NullResolver {
fn resolve(&self, _idx: u32, _module: &str, _field: &str) -> Option<Export> {
None
}
}
pub struct NamedResolverChain<A: NamedResolver + Send + Sync, B: NamedResolver + Send + Sync> {
a: A,
b: B,
}
pub trait ChainableNamedResolver: NamedResolver + Sized + Send + Sync {
fn chain_front<U>(self, other: U) -> NamedResolverChain<U, Self>
where
U: NamedResolver + Send + Sync,
{
NamedResolverChain { a: other, b: self }
}
fn chain_back<U>(self, other: U) -> NamedResolverChain<Self, U>
where
U: NamedResolver + Send + Sync,
{
NamedResolverChain { a: self, b: other }
}
}
impl<T: NamedResolver + Send + Sync> ChainableNamedResolver for T {}
impl<A, B> NamedResolver for NamedResolverChain<A, B>
where
A: NamedResolver + Send + Sync,
B: NamedResolver + Send + Sync,
{
fn resolve_by_name(&self, module: &str, field: &str) -> Option<Export> {
self.a.resolve_by_name(module, field).or_else(|| self.b.resolve_by_name(module, field))
}
}
impl<A, B> Clone for NamedResolverChain<A, B>
where
A: NamedResolver + Clone + Send + Sync,
B: NamedResolver + Clone + Send + Sync,
{
fn clone(&self) -> Self {
Self { a: self.a.clone(), b: self.b.clone() }
}
}