1
2use std::sync::Arc;
3use std::collections::HashMap;
4use std::borrow::Cow;
5use parking_lot::RwLock;
6use elements::{Internal, ValueType};
7use interpreter::Error;
8use interpreter::module::{ModuleInstanceInterface, ExecutionParams, ItemIndex,
9 CallerContext, ExportEntryType, InternalFunctionReference, InternalFunction, FunctionSignature};
10use interpreter::memory::MemoryInstance;
11use interpreter::table::TableInstance;
12use interpreter::value::RuntimeValue;
13use interpreter::variable::{VariableInstance, VariableType};
14
15pub const NATIVE_INDEX_FUNC_MIN: u32 = 10001;
17pub const NATIVE_INDEX_GLOBAL_MIN: u32 = 20001;
19
20pub trait UserFunctionExecutor {
22 fn execute(&mut self, name: &str, context: CallerContext) -> Result<Option<RuntimeValue>, Error>;
24}
25
26#[derive(Debug, Clone)]
28pub enum UserFunctionDescriptor {
29 Static(&'static str, &'static [ValueType], Option<ValueType>),
31 Heap(String, Vec<ValueType>, Option<ValueType>),
33}
34
35impl UserFunctionDescriptor {
36 pub fn statik(name: &'static str, params: &'static [ValueType], result: Option<ValueType>) -> Self {
38 UserFunctionDescriptor::Static(name, params, result)
39 }
40
41 pub fn heap(name: String, params: Vec<ValueType>, result: Option<ValueType>) -> Self {
43 UserFunctionDescriptor::Heap(name, params, result)
44 }
45
46 pub fn name(&self) -> &str {
48 match self {
49 &UserFunctionDescriptor::Static(name, _, _) => name,
50 &UserFunctionDescriptor::Heap(ref name, _, _) => name,
51 }
52 }
53
54 pub fn params(&self) -> &[ValueType] {
56 match self {
57 &UserFunctionDescriptor::Static(_, params, _) => params,
58 &UserFunctionDescriptor::Heap(_, ref params, _) => params,
59 }
60 }
61
62 pub fn return_type(&self) -> Option<ValueType> {
64 match self {
65 &UserFunctionDescriptor::Static(_, _, result) => result,
66 &UserFunctionDescriptor::Heap(_, _, result) => result,
67 }
68 }
69}
70
71pub struct UserDefinedElements<E: UserFunctionExecutor> {
73 pub globals: HashMap<String, Arc<VariableInstance>>,
75 pub functions: Cow<'static, [UserFunctionDescriptor]>,
77 pub executor: Option<E>,
79}
80
81pub struct NativeModuleInstance<E: UserFunctionExecutor> {
83 base: Arc<ModuleInstanceInterface>,
85 executor: RwLock<Option<E>>,
87 functions_by_name: HashMap<String, u32>,
89 functions: Cow<'static, [UserFunctionDescriptor]>,
91 globals_by_name: HashMap<String, u32>,
93 globals: Vec<Arc<VariableInstance>>,
95}
96
97impl<E: UserFunctionExecutor> NativeModuleInstance<E> {
98 pub fn new(base: Arc<ModuleInstanceInterface>, elements: UserDefinedElements<E>) -> Result<Self, Error> {
100 if !elements.functions.is_empty() && elements.executor.is_none() {
101 return Err(Error::Function("trying to construct native module with functions, but without executor".into()));
102 }
103
104 Ok(NativeModuleInstance {
105 base: base,
106 executor: RwLock::new(elements.executor),
107 functions_by_name: elements.functions.iter().enumerate().map(|(i, f)| (f.name().to_owned(), i as u32)).collect(),
108 functions: elements.functions,
109 globals_by_name: elements.globals.iter().enumerate().map(|(i, (g_name, _))| (g_name.to_owned(), i as u32)).collect(),
110 globals: elements.globals.into_iter().map(|(_, g)| g).collect(),
111 })
112 }
113}
114
115impl<E: UserFunctionExecutor> ModuleInstanceInterface for NativeModuleInstance<E> {
116 fn execute_index(&self, index: u32, params: ExecutionParams) -> Result<Option<RuntimeValue>, Error> {
117 self.base.execute_index(index, params)
118 }
119
120 fn execute_export(&self, name: &str, params: ExecutionParams) -> Result<Option<RuntimeValue>, Error> {
121 self.base.execute_export(name, params)
122 }
123
124 fn export_entry<'b>(&self, name: &str, required_type: &ExportEntryType) -> Result<Internal, Error> {
125 if let Some(index) = self.functions_by_name.get(name) {
126 let composite_index = NATIVE_INDEX_FUNC_MIN + *index;
127 match required_type {
128 &ExportEntryType::Any => return Ok(Internal::Function(composite_index)),
129 &ExportEntryType::Function(ref required_type) => {
130 let actual_type = self.function_type(ItemIndex::Internal(composite_index))
131 .expect(
132 "by_name contains index; function_type succeeds for all functions from by_name; qed",
133 );
134 return if actual_type == *required_type {
135 Ok(Internal::Function(composite_index))
136 } else {
137 Err(Error::Validation(format!(
138 "Export function type {} mismatch. Expected function with signature ({:?}) -> {:?} when got with ({:?}) -> {:?}",
139 index,
140 required_type.params(),
141 required_type.return_type(),
142 actual_type.params(),
143 actual_type.return_type()
144 )))
145 };
146 }
147 _ => (),
148 }
149 }
150 if let Some(index) = self.globals_by_name.get(name) {
151 let composite_index = NATIVE_INDEX_GLOBAL_MIN + *index;
152 match required_type {
153 &ExportEntryType::Any => {
154 return Ok(Internal::Global(composite_index))
155 }
156 &ExportEntryType::Global(ref required_type) => {
157 let actual_type = self.globals
158 .get(*index as usize)
159 .expect(
160 "globals_by_name maps to indexes of globals; index read from globals_by_name; qed",
161 )
162 .variable_type();
163 return if actual_type == *required_type {
164 Ok(Internal::Global(composite_index))
165 } else {
166 Err(Error::Validation(format!(
167 "Export global type {} mismatch. Expected type {:?} when got {:?}",
168 index,
169 required_type,
170 actual_type
171 )))
172 };
173 }
174 _ => (),
175 }
176 }
177
178 self.base.export_entry(name, required_type)
179 }
180
181 fn table(&self, index: ItemIndex) -> Result<Arc<TableInstance>, Error> {
182 self.base.table(index)
183 }
184
185 fn memory(&self, index: ItemIndex) -> Result<Arc<MemoryInstance>, Error> {
186 self.base.memory(index)
187 }
188
189 fn global<'b>(&self, global_index: ItemIndex, variable_type: Option<VariableType>, externals: Option<&'b HashMap<String, Arc<ModuleInstanceInterface + 'b>>>) -> Result<Arc<VariableInstance>, Error> {
190 let index = match global_index {
191 ItemIndex::IndexSpace(index) | ItemIndex::Internal(index) => index,
192 ItemIndex::External(_) => unreachable!("trying to get global, exported by native module"),
193 };
194
195 if index < NATIVE_INDEX_GLOBAL_MIN {
196 return self.base.global(global_index, variable_type, externals);
197 }
198
199 self.globals
200 .get((index - NATIVE_INDEX_GLOBAL_MIN) as usize)
201 .cloned()
202 .ok_or(Error::Native(format!("trying to get native global with index {}", index)))
203 }
204
205 fn function_type(&self, function_index: ItemIndex) -> Result<FunctionSignature, Error> {
206 let index = match function_index {
207 ItemIndex::IndexSpace(index) | ItemIndex::Internal(index) => index,
208 ItemIndex::External(_) => unreachable!("trying to call function, exported by native module"),
209 };
210
211 if index < NATIVE_INDEX_FUNC_MIN || index >= NATIVE_INDEX_GLOBAL_MIN {
212 return self.base.function_type(function_index);
213 }
214
215 Ok(FunctionSignature::User(self.functions
216 .get((index - NATIVE_INDEX_FUNC_MIN) as usize)
217 .ok_or(Error::Native(format!("missing native function with index {}", index)))?))
218 }
219
220 fn function_type_by_index(&self, type_index: u32) -> Result<FunctionSignature, Error> {
221 self.function_type(ItemIndex::Internal(type_index))
222 }
223
224 fn function_reference<'b>(&self, index: ItemIndex, externals: Option<&'b HashMap<String, Arc<ModuleInstanceInterface + 'b>>>) -> Result<InternalFunctionReference<'b>, Error> {
225 self.base.function_reference(index, externals)
226 }
227
228 fn function_reference_indirect<'b>(&self, table_idx: u32, type_idx: u32, func_idx: u32, externals: Option<&'b HashMap<String, Arc<ModuleInstanceInterface + 'b>>>) -> Result<InternalFunctionReference<'b>, Error> {
229 self.base.function_reference_indirect(table_idx, type_idx, func_idx, externals)
230 }
231
232 fn function_body<'b>(&'b self, _internal_index: u32) -> Result<Option<InternalFunction<'b>>, Error> {
233 Ok(None)
234 }
235
236 fn call_internal_function(&self, outer: CallerContext, index: u32) -> Result<Option<RuntimeValue>, Error> {
237 if index < NATIVE_INDEX_FUNC_MIN || index >= NATIVE_INDEX_GLOBAL_MIN {
238 return self.base.call_internal_function(outer, index);
239 }
240
241 self.functions
242 .get((index - NATIVE_INDEX_FUNC_MIN) as usize)
243 .ok_or(Error::Native(format!("trying to call native function with index {}", index)).into())
244 .and_then(|f| self.executor.write()
245 .as_mut()
246 .expect("function exists; if function exists, executor must also exists [checked in constructor]; qed")
247 .execute(&f.name(), outer))
248 }
249}
250
251pub fn native_module<'a, E: UserFunctionExecutor + 'a>(base: Arc<ModuleInstanceInterface>, user_elements: UserDefinedElements<E>) -> Result<Arc<ModuleInstanceInterface + 'a>, Error> {
284 Ok(Arc::new(NativeModuleInstance::new(base, user_elements)?))
285}
286
287impl<'a> PartialEq for UserFunctionDescriptor {
288 fn eq(&self, other: &Self) -> bool {
289 self.params() == other.params()
290 && self.return_type() == other.return_type()
291 }
292}