1pub mod memory;
2pub mod state;
3pub mod types;
4#[cfg(feature = "vm-wasmer")]
5pub mod wasmer;
6
7use std::convert::Into;
8use std::fmt::Debug;
9use std::{
10 cell::{Ref, RefCell, RefMut},
11 rc::Rc,
12};
13
14pub use smallvec::SmallVec;
15pub use uptown_funk_macro::host_functions;
16
17pub trait Executor {
19 type Return: Clone;
20
21 #[cfg(feature = "async")]
23 fn async_<R, F>(&self, f: F) -> R
24 where
25 F: std::future::Future<Output = R>;
26
27 fn memory(&self) -> memory::Memory;
29}
30
31pub trait HostFunctions: Sized {
32 type Return: Clone + 'static;
33
34 #[cfg(feature = "vm-wasmtime")]
35 fn add_to_linker<E>(self, executor: E, linker: &mut wasmtime::Linker) -> Self::Return
36 where
37 E: Executor + Clone + 'static;
38
39 #[cfg(feature = "vm-wasmer")]
40 fn add_to_wasmer_linker<E>(
41 self,
42 executor: E,
43 linker: &mut wasmer::WasmerLinker,
44 store: &::wasmer::Store,
45 ) -> Self::Return
46 where
47 E: Executor + Clone + 'static;
48}
49
50pub trait StateMarker: Sized {}
51pub trait Convert<To: Sized>: Sized {
52 fn convert(&mut self) -> &mut To;
53}
54
55impl<T: StateMarker> Convert<T> for T {
56 fn convert(&mut self) -> &mut T {
57 self
58 }
59}
60
61impl<'a, T: StateMarker> Convert<T> for RefMut<'a, T> {
62 fn convert(&mut self) -> &mut T {
63 self
64 }
65}
66
67static mut NOSTATE: () = ();
68
69impl<T: StateMarker> Convert<()> for T {
70 fn convert(&mut self) -> &mut () {
71 unsafe { &mut NOSTATE }
72 }
73}
74
75impl<'a, T: StateMarker> Convert<()> for RefMut<'a, T> {
76 fn convert(&mut self) -> &mut () {
77 unsafe { &mut NOSTATE }
78 }
79}
80
81impl Convert<()> for () {
82 fn convert(&mut self) -> &mut () {
83 self
84 }
85}
86
87pub trait FromWasm {
88 type From;
89 type State: Convert<Self::State> + Convert<()>;
90
91 fn from(
92 state: &mut Self::State,
93 executor: &impl Executor,
94 from: Self::From,
95 ) -> Result<Self, Trap>
96 where
97 Self: Sized;
98}
99
100pub trait ToWasm {
101 type To;
102 type State: Convert<Self::State> + Convert<()>;
103
104 fn to(
105 state: &mut Self::State,
106 executor: &impl Executor,
107 host_value: Self,
108 ) -> Result<Self::To, Trap>;
109}
110
111pub struct StateWrapper<S, E: Executor> {
112 state: Rc<RefCell<S>>,
113 env: Rc<E>,
114}
115
116impl<S, E: Executor> StateWrapper<S, E> {
117 pub fn new(state: S, executor: E) -> Self {
118 Self {
119 state: Rc::new(RefCell::new(state)),
120 env: Rc::new(executor),
121 }
122 }
123
124 pub fn borrow_state(&self) -> Ref<S> {
125 self.state.borrow()
126 }
127
128 pub fn borrow_state_mut(&self) -> RefMut<S> {
129 self.state.borrow_mut()
130 }
131
132 pub fn get_state(&self) -> Rc<RefCell<S>> {
133 self.state.clone()
134 }
135
136 pub fn executor(&self) -> &E {
137 &self.env
138 }
139
140 pub fn memory(&self) -> memory::Memory {
141 self.env.memory()
142 }
143
144 pub fn recover_state(self) -> Result<S, ()> {
145 match Rc::try_unwrap(self.state) {
146 Ok(s) => Ok(s.into_inner()),
147 Err(_) => Err(()),
148 }
149 }
150}
151
152#[cfg(feature = "vm-wasmer")]
154unsafe impl<S, E: Executor> Send for StateWrapper<S, E> {}
155#[cfg(feature = "vm-wasmer")]
156unsafe impl<S, E: Executor> Sync for StateWrapper<S, E> {}
157
158impl<S, E: Executor> Clone for StateWrapper<S, E> {
159 fn clone(&self) -> Self {
160 Self {
161 state: self.state.clone(),
162 env: self.env.clone(),
163 }
164 }
165}
166
167#[cfg(feature = "vm-wasmer")]
168impl<S, E: Executor> ::wasmer::WasmerEnv for StateWrapper<S, E> {
169 fn init_with_instance(
170 &mut self,
171 _: &::wasmer::Instance,
172 ) -> Result<(), ::wasmer::HostEnvInitError> {
173 Ok(())
174 }
175}
176
177#[cfg_attr(feature = "vm-wasmer", derive(thiserror::Error))]
178#[cfg_attr(feature = "vm-wasmer", error("{message}"))]
179pub struct Trap<D = ()>
180where
181 D: 'static,
182{
183 message: String,
184 data: Option<D>,
185}
186
187impl<D> Debug for Trap<D> {
188 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
189 Debug::fmt(&self.message, f)
190 }
191}
192
193impl Trap<()> {
194 pub fn new<I: Into<String>>(message: I) -> Self {
195 Self {
196 message: message.into(),
197 data: None,
198 }
199 }
200
201 pub fn with_data<D: 'static>(self, data: D) -> Trap<D> {
202 Trap {
203 message: self.message,
204 data: Some(data),
205 }
206 }
207
208 pub fn try_option<R: Debug>(result: Option<R>) -> Result<R, Trap> {
209 match result {
210 Some(r) => Ok(r),
211 None => Err(Trap::new(
212 "Host function trapped: Memory location not inside wasm guest",
213 )),
214 }
215 }
216
217 pub fn try_result<R: Debug, E: Debug>(result: Result<R, E>) -> Result<R, Trap> {
218 match result {
219 Ok(r) => Ok(r),
220 Err(_) => {
221 let message = format!("Host function trapped: {:?}", result);
222 Err(Trap::new(message))
223 }
224 }
225 }
226}
227
228impl ToWasm for Trap {
229 type To = ();
230 type State = ();
231
232 fn to(_: &mut (), _: &impl Executor, v: Self) -> Result<(), Trap> {
233 Err(v)
234 }
235}
236
237#[cfg(feature = "vm-wasmtime")]
238impl From<Trap> for wasmtime::Trap {
239 fn from(trap: Trap) -> Self {
240 wasmtime::Trap::new(trap.message)
241 }
242}
243
244#[repr(C)]
245pub struct IoVecT {
246 pub ptr: u32,
247 pub len: u32,
248}