1use crate::addrs::GlobalAddr;
2use crate::core::reader::types::global::GlobalType;
3use crate::resumable::{ResumableRef, RunState};
4use alloc::borrow::{Cow, ToOwned};
5use alloc::vec::Vec;
6
7use const_interpreter_loop::run_const_span;
8use store::addrs::{FuncAddr, ModuleAddr};
9use store::ExternVal;
10use store::HaltExecutionError;
11use value_stack::Stack;
12
13use crate::core::reader::types::{FuncType, ResultType};
14use crate::execution::assert_validated::UnwrapValidatedExt;
15use crate::execution::config::Config;
16use crate::execution::store::Store;
17use crate::execution::value::Value;
18use crate::interop::InteropValueList;
19use crate::{RuntimeError, ValidationInfo};
20
21pub(crate) mod assert_validated;
22pub mod config;
23pub mod const_interpreter_loop;
24pub mod error;
25pub mod interop;
26mod interpreter_loop;
27pub mod linker;
28pub(crate) mod little_endian;
29pub mod registry;
30pub mod resumable;
31pub mod store;
32pub mod value;
33pub mod value_stack;
34
35pub const DEFAULT_MODULE: &str = "__interpreter_default__";
37
38pub struct RuntimeInstance<'b, T: Config = ()> {
39 pub store: Store<'b, T>,
40}
41
42impl<T: Config + Default> Default for RuntimeInstance<'_, T> {
43 fn default() -> Self {
44 Self::new(T::default())
45 }
46}
47
48impl<'b, T: Config> RuntimeInstance<'b, T> {
49 pub fn new(user_data: T) -> Self {
50 RuntimeInstance {
51 store: Store::new(user_data),
52 }
53 }
54
55 pub fn new_with_default_module(
57 user_data: T,
58 validation_info: &'_ ValidationInfo<'b>,
59 ) -> Result<(Self, ModuleAddr), RuntimeError> {
60 let mut instance = Self::new(user_data);
61 let module_addr = instance.add_module(DEFAULT_MODULE, validation_info, None)?;
62 Ok((instance, module_addr))
63 }
64
65 pub fn new_named(
67 user_data: T,
68 module_name: &str,
69 validation_info: &'_ ValidationInfo<'b>,
70 ) -> Result<(Self, ModuleAddr), RuntimeError> {
72 let mut instance = Self::new(user_data);
73 let module_addr = instance.add_module(module_name, validation_info, None)?;
74 Ok((instance, module_addr))
75 }
76
77 pub fn add_module(
80 &mut self,
81 module_name: &str,
82 validation_info: &'_ ValidationInfo<'b>,
83 maybe_fuel: Option<u32>,
84 ) -> Result<ModuleAddr, RuntimeError> {
85 self.store
86 .add_module(module_name, validation_info, maybe_fuel)
87 }
88
89 pub fn get_module_by_name(&self, module_name: &str) -> Option<ModuleAddr> {
90 self.store
92 .registry
93 .lookup_module(Cow::Owned(module_name.to_owned()))
94 }
95
96 pub fn get_function_by_name(
97 &self,
98 module_name: &str,
99 function_name: &str,
100 ) -> Result<FuncAddr, RuntimeError> {
101 self.store
103 .registry
104 .lookup(
105 Cow::Owned(module_name.to_owned()),
106 Cow::Owned(function_name.to_owned()),
107 )?
108 .as_func()
109 .ok_or(RuntimeError::FunctionNotFound)
110 }
111
112 pub fn get_function_by_index(
113 &self,
114 module_addr: ModuleAddr,
115 function_idx: usize,
116 ) -> Result<FuncAddr, RuntimeError> {
117 let module_inst = self.store.modules.get(module_addr);
118 let function = *module_inst
119 .func_addrs
120 .get(function_idx)
121 .ok_or(RuntimeError::FunctionNotFound)?;
122
123 Ok(function)
124 }
125
126 pub fn invoke_typed<Params: InteropValueList, Returns: InteropValueList>(
128 &mut self,
129 function: FuncAddr,
130 params: Params,
131 ) -> Result<Returns, RuntimeError> {
133 self.invoke(function, params.into_values())
134 .map(|values| Returns::try_from_values(values.into_iter()).unwrap_validated())
135 }
136
137 pub fn invoke(
139 &mut self,
140 function: FuncAddr,
141 params: Vec<Value>,
142 ) -> Result<Vec<Value>, RuntimeError> {
143 self.store
144 .invoke(function, params, None)
145 .map(|run_state| match run_state {
146 RunState::Finished(values) => values,
147 _ => unreachable!("non metered invoke call"),
148 })
149 }
150
151 pub fn create_resumable(
155 &self,
156 function: FuncAddr,
157 params: Vec<Value>,
158 fuel: u32,
159 ) -> Result<ResumableRef, RuntimeError> {
160 self.store.create_resumable(function, params, Some(fuel))
161 }
162
163 pub fn resume(&mut self, resumable_ref: ResumableRef) -> Result<RunState, RuntimeError> {
166 self.store.resume(resumable_ref)
167 }
168
169 pub fn access_fuel_mut<R>(
188 &mut self,
189 resumable_ref: &mut ResumableRef,
190 f: impl FnOnce(&mut Option<u32>) -> R,
191 ) -> Result<R, RuntimeError> {
192 self.store.access_fuel_mut(resumable_ref, f)
193 }
194
195 pub fn add_host_function_typed<Params: InteropValueList, Returns: InteropValueList>(
199 &mut self,
200 module_name: &str,
201 name: &str,
202 host_func: fn(&mut T, Vec<Value>) -> Result<Vec<Value>, HaltExecutionError>,
203 ) -> Result<FuncAddr, RuntimeError> {
204 let host_func_ty = FuncType {
205 params: ResultType {
206 valtypes: Vec::from(Params::TYS),
207 },
208 returns: ResultType {
209 valtypes: Vec::from(Returns::TYS),
210 },
211 };
212 self.add_host_function(module_name, name, host_func_ty, host_func)
213 }
214
215 pub fn add_host_function(
216 &mut self,
217 module_name: &str,
218 name: &str,
219 host_func_ty: FuncType,
220 host_func: fn(&mut T, Vec<Value>) -> Result<Vec<Value>, HaltExecutionError>,
221 ) -> Result<FuncAddr, RuntimeError> {
222 let function = self.store.func_alloc(host_func_ty, host_func);
223 self.store.registry.register(
224 module_name.to_owned().into(),
225 name.to_owned().into(),
226 store::ExternVal::Func(function),
227 )?;
228 Ok(function)
229 }
230
231 pub fn user_data(&self) -> &T {
232 &self.store.user_data
233 }
234
235 pub fn user_data_mut(&mut self) -> &mut T {
236 &mut self.store.user_data
237 }
238
239 pub fn global_type(&self, global_addr: GlobalAddr) -> GlobalType {
241 self.store.global_type(global_addr)
242 }
243
244 pub fn global_read(&self, global_addr: GlobalAddr) -> Value {
246 self.store.global_read(global_addr)
247 }
248
249 pub fn global_write(
255 &mut self,
256 global_addr: GlobalAddr,
257 val: Value,
258 ) -> Result<(), RuntimeError> {
259 self.store.global_write(global_addr, val)
260 }
261
262 pub fn lookup_export(
264 &self,
265 module_name: Cow<'static, str>,
266 name: Cow<'static, str>,
267 ) -> Result<ExternVal, RuntimeError> {
268 self.store.registry.lookup(module_name, name).copied()
269 }
270}
271
272pub fn host_function_wrapper<Params: InteropValueList, Results: InteropValueList>(
290 params: Vec<Value>,
291 f: impl FnOnce(Params) -> Result<Results, HaltExecutionError>,
292) -> Result<Vec<Value>, HaltExecutionError> {
293 let params =
294 Params::try_from_values(params.into_iter()).expect("Params match the actual parameters");
295 f(params).map(Results::into_values)
296}