1#![warn(missing_docs)]
4
5use ayaka_plugin::*;
6use std::{
7 collections::HashMap,
8 sync::{Arc, Mutex},
9};
10use wasmer::*;
11
12unsafe fn mem_slice<R>(
13 store: &impl AsStoreRef,
14 memory: &Memory,
15 start: i32,
16 len: i32,
17 f: impl FnOnce(&[u8]) -> R,
18) -> R {
19 f(memory
20 .view(store)
21 .data_unchecked()
22 .get_unchecked(start as usize..)
23 .get_unchecked(..len as usize))
24}
25
26unsafe fn mem_slice_mut<R>(
27 store: &impl AsStoreRef,
28 memory: &Memory,
29 start: i32,
30 len: i32,
31 f: impl FnOnce(&mut [u8]) -> R,
32) -> R {
33 f(memory
34 .view(store)
35 .data_unchecked_mut()
36 .get_unchecked_mut(start as usize..)
37 .get_unchecked_mut(..len as usize))
38}
39
40type HostStore = Arc<Mutex<Store>>;
41
42pub struct WasmerModule {
44 store: HostStore,
45 instance: Instance,
46 memory: Memory,
47 abi_free: TypedFunction<(i32, i32), ()>,
48 abi_alloc: TypedFunction<i32, i32>,
49}
50
51impl WasmerModule {
52 fn new(store: HostStore, instance: Instance) -> Result<Self> {
54 let memory = instance.exports.get_memory(MEMORY_NAME)?.clone();
55 let inner_store = store.lock().unwrap();
56 let abi_free = instance
57 .exports
58 .get_typed_function(&inner_store.as_store_ref(), ABI_FREE_NAME)?;
59 let abi_alloc = instance
60 .exports
61 .get_typed_function(&inner_store.as_store_ref(), ABI_ALLOC_NAME)?;
62 drop(inner_store);
63 Ok(Self {
64 store,
65 instance,
66 memory,
67 abi_free,
68 abi_alloc,
69 })
70 }
71
72 fn call_impl<T>(
73 &self,
74 mut store: StoreMut,
75 name: &str,
76 data: &[u8],
77 f: impl FnOnce(&[u8]) -> Result<T>,
78 ) -> Result<T> {
79 let func = self
80 .instance
81 .exports
82 .get_typed_function::<(i32, i32), u64>(&store, name)?;
83
84 let ptr = self.abi_alloc.call(&mut store, data.len() as i32)?;
85 unsafe {
86 mem_slice_mut(&store, &self.memory, ptr, data.len() as i32, |s| {
87 s.copy_from_slice(data)
88 })
89 };
90
91 let res = func.call(&mut store, data.len() as i32, ptr);
92
93 self.abi_free.call(&mut store, ptr, data.len() as i32)?;
94
95 let res = res?;
96 let (len, res) = ((res >> 32) as i32, (res & 0xFFFFFFFF) as i32);
97
98 let res_data = unsafe { mem_slice(&store, &self.memory, res, len, |s| f(s)) };
99
100 self.abi_free.call(&mut store, res, len)?;
101
102 let res_data = res_data?;
103 Ok(res_data)
104 }
105}
106
107impl RawModule for WasmerModule {
108 type Linker = WasmerLinker;
109
110 type LinkerHandle<'a> = WasmerLinkerHandle<'a>;
111
112 type Func = WasmerFunction;
113
114 fn call<T>(&self, name: &str, data: &[u8], f: impl FnOnce(&[u8]) -> Result<T>) -> Result<T> {
115 self.call_impl(self.store.lock().unwrap().as_store_mut(), name, data, f)
116 }
117}
118
119#[doc(hidden)]
120#[derive(Clone)]
121pub struct RuntimeInstanceData {
122 memory: Option<Memory>,
123 abi_alloc: Option<TypedFunction<i32, i32>>,
124 #[allow(clippy::type_complexity)]
125 func: Arc<dyn (Fn(WasmerLinkerHandle, i32, i32) -> Result<Vec<u8>>) + Send + Sync + 'static>,
126}
127
128impl RuntimeInstanceData {
129 pub fn new(
130 func: impl (Fn(WasmerLinkerHandle, i32, i32) -> Result<Vec<u8>>) + Send + Sync + 'static,
131 ) -> Self {
132 Self {
133 memory: None,
134 abi_alloc: None,
135 func: Arc::new(func),
136 }
137 }
138
139 pub fn set_memory(&mut self, memory: Memory) {
140 self.memory = Some(memory);
141 }
142
143 pub fn memory(&self) -> &Memory {
144 self.memory.as_ref().expect("memory should be set first")
145 }
146
147 pub fn set_abi_alloc(&mut self, func: TypedFunction<i32, i32>) {
148 self.abi_alloc = Some(func);
149 }
150
151 pub fn call(mut this: FunctionEnvMut<Self>, len: i32, ptr: i32) -> u64 {
152 unsafe {
154 let memory = this.data().memory().clone();
155 let data = {
156 let func = this.data().func.clone();
157 let handle = WasmerLinkerHandle {
158 store: this.as_store_mut(),
159 memory: memory.clone(),
160 };
161 (func)(handle, ptr, len).unwrap()
162 };
163 let abi_alloc = this.data().abi_alloc.clone().unwrap();
164 let ptr = abi_alloc.call(&mut this, data.len() as i32).unwrap();
165 mem_slice_mut(&this, &memory, ptr, data.len() as i32, |slice| {
166 slice.copy_from_slice(&data);
167 });
168 ((data.len() as u64) << 32) | (ptr as u64)
169 }
170 }
171}
172
173pub struct WasmerLinker {
175 store: HostStore,
176 imports: HashMap<String, HashMap<String, WasmerFunction>>,
177}
178
179impl WasmerLinker {
180 fn wrap_impl(
181 store: &mut impl AsStoreMut,
182 func: WasmerFunction,
183 ) -> (Function, Option<FunctionEnv<RuntimeInstanceData>>) {
184 let env_data = func.0;
185 let env = FunctionEnv::new(store, env_data);
186 let func = Function::new_typed_with_env(store, &env, RuntimeInstanceData::call);
187 (func, Some(env))
188 }
189}
190
191impl Linker<WasmerModule> for WasmerLinker {
192 type Config = ();
193
194 fn new(_: ()) -> Result<Self> {
195 let store = Store::default();
196 Ok(Self {
197 store: Arc::new(Mutex::new(store)),
198 imports: HashMap::default(),
199 })
200 }
201
202 fn create(&self, binary: &[u8]) -> Result<WasmerModule> {
203 let instance = {
204 let mut store = self.store.lock().unwrap();
205 let module = Module::from_binary(&store.as_store_ref(), binary)?;
206 let mut imports = Imports::default();
207 let mut envs = vec![];
208 for (ns, funcs) in &self.imports {
209 imports.register_namespace(
210 ns,
211 funcs.iter().map(|(name, func)| {
212 (
213 name.clone(),
214 Extern::Function({
215 let (func, env) =
216 Self::wrap_impl(&mut store.as_store_mut(), func.clone());
217 if let Some(env) = env {
218 envs.push(env)
219 }
220 func
221 }),
222 )
223 }),
224 );
225 }
226 let instance = Instance::new(&mut store.as_store_mut(), &module, &imports)?;
227 let memory = instance.exports.get_memory(MEMORY_NAME)?;
228 let abi_alloc = instance
229 .exports
230 .get_typed_function(&store.as_store_ref(), ABI_ALLOC_NAME)?;
231 let mut store = store.as_store_mut();
232 for env in &envs {
233 let env_mut = env.as_mut(&mut store);
234 env_mut.set_memory(memory.clone());
235 env_mut.set_abi_alloc(abi_alloc.clone());
236 }
237 instance
238 };
239 let host = WasmerModule::new(self.store.clone(), instance)?;
240 Ok(host)
241 }
242
243 fn import(
244 &mut self,
245 ns: impl Into<String>,
246 funcs: HashMap<String, WasmerFunction>,
247 ) -> Result<()> {
248 self.imports.insert(ns.into(), funcs);
249 Ok(())
250 }
251
252 fn wrap_raw(
253 &self,
254 f: impl (Fn(WasmerLinkerHandle, i32, i32) -> Result<Vec<u8>>) + Send + Sync + 'static,
255 ) -> WasmerFunction {
256 WasmerFunction(RuntimeInstanceData::new(f))
257 }
258}
259
260#[derive(Clone)]
262pub struct WasmerFunction(RuntimeInstanceData);
263
264pub struct WasmerLinkerHandle<'a> {
266 store: StoreMut<'a>,
267 memory: Memory,
268}
269
270impl<'a> LinkerHandle<'a, WasmerModule> for WasmerLinkerHandle<'a> {
271 fn call<T>(
272 &mut self,
273 m: &WasmerModule,
274 name: &str,
275 data: &[u8],
276 f: impl FnOnce(&[u8]) -> Result<T>,
277 ) -> Result<T> {
278 m.call_impl(self.store.as_store_mut(), name, data, f)
279 }
280
281 fn slice<T>(&self, start: i32, len: i32, f: impl FnOnce(&[u8]) -> T) -> T {
282 unsafe { mem_slice(&self.store.as_store_ref(), &self.memory, start, len, f) }
283 }
284
285 fn slice_mut<T>(&mut self, start: i32, len: i32, f: impl FnOnce(&mut [u8]) -> T) -> T {
286 unsafe { mem_slice_mut(&self.store.as_store_ref(), &self.memory, start, len, f) }
287 }
288}