extism_runtime/
function.rs1use crate::{Error, Internal};
2
3#[derive(Debug, Clone, Hash, Eq, PartialEq)]
5#[repr(C)]
6pub enum ValType {
7 I32,
11 I64,
13 F32,
15 F64,
17 V128,
19 FuncRef,
21 ExternRef,
23}
24
25impl From<wasmtime::ValType> for ValType {
26 fn from(value: wasmtime::ValType) -> Self {
27 use wasmtime::ValType::*;
28 match value {
29 I32 => ValType::I32,
30 I64 => ValType::I64,
31 F32 => ValType::F32,
32 F64 => ValType::F64,
33 V128 => ValType::V128,
34 FuncRef => ValType::FuncRef,
35 ExternRef => ValType::ExternRef,
36 }
37 }
38}
39
40impl From<ValType> for wasmtime::ValType {
41 fn from(value: ValType) -> Self {
42 use ValType::*;
43 match value {
44 I32 => wasmtime::ValType::I32,
45 I64 => wasmtime::ValType::I64,
46 F32 => wasmtime::ValType::F32,
47 F64 => wasmtime::ValType::F64,
48 V128 => wasmtime::ValType::V128,
49 FuncRef => wasmtime::ValType::FuncRef,
50 ExternRef => wasmtime::ValType::ExternRef,
51 }
52 }
53}
54
55pub type Val = wasmtime::Val;
56
57pub struct UserData {
58 ptr: *mut std::ffi::c_void,
59 free: Option<extern "C" fn(_: *mut std::ffi::c_void)>,
60 is_any: bool,
61}
62
63extern "C" fn free_any(ptr: *mut std::ffi::c_void) {
64 let ptr = ptr as *mut dyn std::any::Any;
65 unsafe { drop(Box::from_raw(ptr)) }
66}
67
68impl UserData {
69 pub fn new_pointer(
70 ptr: *mut std::ffi::c_void,
71 free: Option<extern "C" fn(_: *mut std::ffi::c_void)>,
72 ) -> Self {
73 UserData {
74 ptr,
75 free,
76 is_any: false,
77 }
78 }
79
80 pub fn new<T: std::any::Any>(x: T) -> Self {
81 let ptr = Box::into_raw(Box::new(x)) as *mut _;
82 UserData {
83 ptr,
84 free: Some(free_any),
85 is_any: true,
86 }
87 }
88
89 pub fn is_null(&self) -> bool {
90 self.ptr.is_null()
91 }
92
93 pub fn as_ptr(&self) -> *mut std::ffi::c_void {
94 self.ptr
95 }
96
97 pub(crate) fn make_copy(&self) -> Self {
98 UserData {
99 ptr: self.ptr,
100 free: None,
101 is_any: self.is_any,
102 }
103 }
104
105 pub fn any(&self) -> Option<&dyn std::any::Any> {
106 if !self.is_any || self.is_null() {
107 return None;
108 }
109
110 unsafe { Some(&*self.ptr) }
111 }
112
113 pub fn any_mut(&mut self) -> Option<&mut dyn std::any::Any> {
114 if !self.is_any || self.is_null() {
115 return None;
116 }
117
118 unsafe { Some(&mut *self.ptr) }
119 }
120}
121
122impl Default for UserData {
123 fn default() -> Self {
124 UserData {
125 ptr: std::ptr::null_mut(),
126 free: None,
127 is_any: false,
128 }
129 }
130}
131
132impl Drop for UserData {
133 fn drop(&mut self) {
134 if self.ptr.is_null() {
135 return;
136 }
137
138 if let Some(free) = self.free {
139 free(self.ptr);
140 }
141
142 self.ptr = std::ptr::null_mut();
143 }
144}
145
146unsafe impl Send for UserData {}
147unsafe impl Sync for UserData {}
148
149type FunctionInner = dyn Fn(wasmtime::Caller<Internal>, &[wasmtime::Val], &mut [wasmtime::Val]) -> Result<(), Error>
150 + Sync
151 + Send;
152
153#[derive(Clone)]
154pub struct Function {
155 pub(crate) name: String,
156 pub(crate) ty: wasmtime::FuncType,
157 pub(crate) f: std::sync::Arc<FunctionInner>,
158 pub(crate) namespace: Option<String>,
159 pub(crate) _user_data: std::sync::Arc<UserData>,
160}
161
162impl Function {
163 pub fn new<F>(
164 name: impl Into<String>,
165 args: impl IntoIterator<Item = ValType>,
166 returns: impl IntoIterator<Item = ValType>,
167 user_data: Option<UserData>,
168 f: F,
169 ) -> Function
170 where
171 F: 'static
172 + Fn(&mut Internal, &[Val], &mut [Val], UserData) -> Result<(), Error>
173 + Sync
174 + Send,
175 {
176 let user_data = user_data.unwrap_or_default();
177 let data = user_data.make_copy();
178 Function {
179 name: name.into(),
180 ty: wasmtime::FuncType::new(
181 args.into_iter().map(wasmtime::ValType::from),
182 returns.into_iter().map(wasmtime::ValType::from),
183 ),
184 f: std::sync::Arc::new(move |mut caller, inp, outp| {
185 f(caller.data_mut(), inp, outp, data.make_copy())
186 }),
187 namespace: None,
188 _user_data: std::sync::Arc::new(user_data),
189 }
190 }
191
192 pub fn name(&self) -> &str {
193 &self.name
194 }
195
196 pub fn namespace(&self) -> Option<&str> {
197 self.namespace.as_deref()
198 }
199
200 pub fn set_namespace(&mut self, namespace: impl Into<String>) {
201 self.namespace = Some(namespace.into());
202 }
203
204 pub fn with_namespace(mut self, namespace: impl Into<String>) -> Self {
205 self.set_namespace(namespace);
206 self
207 }
208
209 pub fn ty(&self) -> &wasmtime::FuncType {
210 &self.ty
211 }
212}