1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
use std::sync::Arc;
use std::collections::HashMap;
use parking_lot::RwLock;
use elements::{FunctionType, Internal, ValueType};
use interpreter::Error;
use interpreter::module::{ModuleInstanceInterface, ExecutionParams, ItemIndex,
CallerContext};
use interpreter::memory::MemoryInstance;
use interpreter::table::TableInstance;
use interpreter::value::RuntimeValue;
use interpreter::variable::VariableInstance;
pub const NATIVE_INDEX_FUNC_MIN: u32 = 10001;
pub trait UserFunctionExecutor {
fn execute(&mut self, name: &str, context: CallerContext) -> Result<Option<RuntimeValue>, Error>;
}
pub struct UserFunction {
pub name: String,
pub params: Vec<ValueType>,
pub result: Option<ValueType>,
}
pub struct UserFunctions<'a> {
pub functions: Vec<UserFunction>,
pub executor: &'a mut UserFunctionExecutor,
}
pub struct NativeModuleInstance<'a> {
env: Arc<ModuleInstanceInterface>,
executor: RwLock<&'a mut UserFunctionExecutor>,
by_name: HashMap<String, u32>,
functions: Vec<UserFunction>,
}
impl<'a> NativeModuleInstance<'a> {
pub fn new(env: Arc<ModuleInstanceInterface>, functions: UserFunctions<'a>) -> Result<Self, Error> {
Ok(NativeModuleInstance {
env: env,
executor: RwLock::new(functions.executor),
by_name: functions.functions.iter().enumerate().map(|(i, f)| (f.name.clone(), i as u32)).collect(),
functions: functions.functions,
})
}
}
impl<'a> ModuleInstanceInterface for NativeModuleInstance<'a> {
fn execute_main(&self, params: ExecutionParams) -> Result<Option<RuntimeValue>, Error> {
self.env.execute_main(params)
}
fn execute_index(&self, index: u32, params: ExecutionParams) -> Result<Option<RuntimeValue>, Error> {
self.env.execute_index(index, params)
}
fn execute_export(&self, name: &str, params: ExecutionParams) -> Result<Option<RuntimeValue>, Error> {
self.env.execute_export(name, params)
}
fn export_entry(&self, name: &str) -> Result<Internal, Error> {
if let Some(index) = self.by_name.get(name) {
return Ok(Internal::Function(NATIVE_INDEX_FUNC_MIN + *index));
}
self.env.export_entry(name)
}
fn table(&self, index: ItemIndex) -> Result<Arc<TableInstance>, Error> {
self.env.table(index)
}
fn memory(&self, index: ItemIndex) -> Result<Arc<MemoryInstance>, Error> {
self.env.memory(index)
}
fn global(&self, index: ItemIndex) -> Result<Arc<VariableInstance>, Error> {
self.env.global(index)
}
fn call_function(&self, outer: CallerContext, index: ItemIndex) -> Result<Option<RuntimeValue>, Error> {
self.env.call_function(outer, index)
}
fn call_function_indirect(&self, outer: CallerContext, table_index: ItemIndex, type_index: u32, func_index: u32) -> Result<Option<RuntimeValue>, Error> {
self.env.call_function_indirect(outer, table_index, type_index, func_index)
}
fn call_internal_function(&self, outer: CallerContext, index: u32, function_type: Option<&FunctionType>) -> Result<Option<RuntimeValue>, Error> {
if index < NATIVE_INDEX_FUNC_MIN {
return self.env.call_internal_function(outer, index, function_type);
}
self.functions
.get((index - NATIVE_INDEX_FUNC_MIN) as usize)
.ok_or(Error::Native(format!("trying to call native function with index {}", index)))
.and_then(|f| self.executor.write().execute(&f.name, outer))
}
}
pub fn env_native_module(env: Arc<ModuleInstanceInterface>, user_functions: UserFunctions) -> Result<NativeModuleInstance, Error> {
NativeModuleInstance::new(env, user_functions)
}