1use crate::{WasmtimeStoreContextMut, abort};
2use std::{mem::MaybeUninit, num::NonZeroU64, os::raw::c_void, ptr};
3use wasmtime::{AnyRef, ExternRef, I31, OwnedRooted, Ref, RootScope, Val};
4
5#[derive(Clone)]
18pub struct wasm_ref_t {
19 pub(crate) r: Ref,
20}
21
22wasmtime_c_api_macros::declare_own!(wasm_ref_t);
23
24impl wasm_ref_t {
25 pub(crate) fn new(r: Ref) -> Option<Box<wasm_ref_t>> {
26 if r.is_null() || !r.is_func() {
27 None
28 } else {
29 Some(Box::new(wasm_ref_t { r }))
30 }
31 }
32}
33
34pub(crate) fn ref_to_val(r: &wasm_ref_t) -> Val {
35 Val::from(r.r.clone())
36}
37
38#[unsafe(no_mangle)]
39pub extern "C" fn wasm_ref_copy(r: Option<&wasm_ref_t>) -> Option<Box<wasm_ref_t>> {
40 r.map(|r| Box::new(r.clone()))
41}
42
43#[unsafe(no_mangle)]
44pub extern "C" fn wasm_ref_same(_a: Option<&wasm_ref_t>, _b: Option<&wasm_ref_t>) -> bool {
45 abort("wasm_ref_same")
47}
48
49#[unsafe(no_mangle)]
50pub extern "C" fn wasm_ref_get_host_info(_ref: Option<&wasm_ref_t>) -> *mut c_void {
51 std::ptr::null_mut()
52}
53
54#[unsafe(no_mangle)]
55pub extern "C" fn wasm_ref_set_host_info(_ref: Option<&wasm_ref_t>, _info: *mut c_void) {
56 abort("wasm_ref_set_host_info")
57}
58
59#[unsafe(no_mangle)]
60pub extern "C" fn wasm_ref_set_host_info_with_finalizer(
61 _ref: Option<&wasm_ref_t>,
62 _info: *mut c_void,
63 _finalizer: Option<extern "C" fn(*mut c_void)>,
64) {
65 abort("wasm_ref_set_host_info_with_finalizer")
66}
67
68#[unsafe(no_mangle)]
69pub extern "C" fn wasm_ref_as_extern(_ref: Option<&wasm_ref_t>) -> Option<&crate::wasm_extern_t> {
70 abort("wasm_ref_as_extern")
71}
72
73#[unsafe(no_mangle)]
74pub extern "C" fn wasm_ref_as_extern_const(
75 _ref: Option<&wasm_ref_t>,
76) -> Option<&crate::wasm_extern_t> {
77 abort("wasm_ref_as_extern_const")
78}
79
80#[unsafe(no_mangle)]
81pub extern "C" fn wasm_ref_as_foreign(_ref: Option<&wasm_ref_t>) -> Option<&crate::wasm_foreign_t> {
82 abort("wasm_ref_as_foreign")
83}
84
85#[unsafe(no_mangle)]
86pub extern "C" fn wasm_ref_as_foreign_const(
87 _ref: Option<&wasm_ref_t>,
88) -> Option<&crate::wasm_foreign_t> {
89 abort("wasm_ref_as_foreign_const")
90}
91
92#[unsafe(no_mangle)]
93pub extern "C" fn wasm_ref_as_func(_ref: Option<&wasm_ref_t>) -> Option<&crate::wasm_func_t> {
94 abort("wasm_ref_as_func")
95}
96
97#[unsafe(no_mangle)]
98pub extern "C" fn wasm_ref_as_func_const(_ref: Option<&wasm_ref_t>) -> Option<&crate::wasm_func_t> {
99 abort("wasm_ref_as_func_const")
100}
101
102#[unsafe(no_mangle)]
103pub extern "C" fn wasm_ref_as_global(_ref: Option<&wasm_ref_t>) -> Option<&crate::wasm_global_t> {
104 abort("wasm_ref_as_global")
105}
106
107#[unsafe(no_mangle)]
108pub extern "C" fn wasm_ref_as_global_const(
109 _ref: Option<&wasm_ref_t>,
110) -> Option<&crate::wasm_global_t> {
111 abort("wasm_ref_as_global_const")
112}
113
114#[unsafe(no_mangle)]
115pub extern "C" fn wasm_ref_as_instance(
116 _ref: Option<&wasm_ref_t>,
117) -> Option<&crate::wasm_instance_t> {
118 abort("wasm_ref_as_instance")
119}
120
121#[unsafe(no_mangle)]
122pub extern "C" fn wasm_ref_as_instance_const(
123 _ref: Option<&wasm_ref_t>,
124) -> Option<&crate::wasm_instance_t> {
125 abort("wasm_ref_as_instance_const")
126}
127
128#[unsafe(no_mangle)]
129pub extern "C" fn wasm_ref_as_memory(_ref: Option<&wasm_ref_t>) -> Option<&crate::wasm_memory_t> {
130 abort("wasm_ref_as_memory")
131}
132
133#[unsafe(no_mangle)]
134pub extern "C" fn wasm_ref_as_memory_const(
135 _ref: Option<&wasm_ref_t>,
136) -> Option<&crate::wasm_memory_t> {
137 abort("wasm_ref_as_memory_const")
138}
139
140#[unsafe(no_mangle)]
141pub extern "C" fn wasm_ref_as_module(_ref: Option<&wasm_ref_t>) -> Option<&crate::wasm_module_t> {
142 abort("wasm_ref_as_module")
143}
144
145#[unsafe(no_mangle)]
146pub extern "C" fn wasm_ref_as_module_const(
147 _ref: Option<&wasm_ref_t>,
148) -> Option<&crate::wasm_module_t> {
149 abort("wasm_ref_as_module_const")
150}
151
152#[unsafe(no_mangle)]
153pub extern "C" fn wasm_ref_as_table(_ref: Option<&wasm_ref_t>) -> Option<&crate::wasm_table_t> {
154 abort("wasm_ref_as_table")
155}
156
157#[unsafe(no_mangle)]
158pub extern "C" fn wasm_ref_as_table_const(
159 _ref: Option<&wasm_ref_t>,
160) -> Option<&crate::wasm_table_t> {
161 abort("wasm_ref_as_table_const")
162}
163
164#[unsafe(no_mangle)]
165pub extern "C" fn wasm_ref_as_trap(_ref: Option<&wasm_ref_t>) -> Option<&crate::wasm_trap_t> {
166 abort("wasm_ref_as_trap")
167}
168
169#[unsafe(no_mangle)]
170pub extern "C" fn wasm_ref_as_trap_const(_ref: Option<&wasm_ref_t>) -> Option<&crate::wasm_trap_t> {
171 abort("wasm_ref_as_trap_const")
172}
173
174#[derive(Clone)]
175#[repr(C)]
176pub struct wasm_foreign_t {}
177
178wasmtime_c_api_macros::declare_ref!(wasm_foreign_t);
179
180#[unsafe(no_mangle)]
181pub extern "C" fn wasm_foreign_new(_store: &crate::wasm_store_t) -> Box<wasm_foreign_t> {
182 abort("wasm_foreign_new")
183}
184
185macro_rules! ref_wrapper {
194 ($wasmtime:ident => $c:ident) => {
195 pub struct $c {
196 store_id: u64,
197 a: u32,
198 b: u32,
199 c: *const (),
200 }
201
202 impl $c {
203 pub unsafe fn as_wasmtime(&self) -> Option<OwnedRooted<$wasmtime>> {
204 let store_id = NonZeroU64::new(self.store_id)?;
205 Some(OwnedRooted::from_borrowed_raw_parts_for_c_api(
206 store_id, self.a, self.b, self.c,
207 ))
208 }
209
210 pub unsafe fn from_wasmtime(self) -> Option<OwnedRooted<$wasmtime>> {
211 let store_id = NonZeroU64::new(self.store_id)?;
212 Some(OwnedRooted::from_owned_raw_parts_for_c_api(
213 store_id, self.a, self.b, self.c,
214 ))
215 }
216 }
217
218 impl From<Option<OwnedRooted<$wasmtime>>> for $c {
219 fn from(rooted: Option<OwnedRooted<$wasmtime>>) -> $c {
220 let mut ret = $c {
221 store_id: 0,
222 a: 0,
223 b: 0,
224 c: core::ptr::null(),
225 };
226 if let Some(rooted) = rooted {
227 let (store_id, a, b, c) = rooted.into_parts_for_c_api();
228 ret.store_id = store_id.get();
229 ret.a = a;
230 ret.b = b;
231 ret.c = c;
232 }
233 ret
234 }
235 }
236
237 unsafe impl Send for $c {}
242 unsafe impl Sync for $c {}
243 };
244}
245
246ref_wrapper!(AnyRef => wasmtime_anyref_t);
247ref_wrapper!(ExternRef => wasmtime_externref_t);
248
249#[unsafe(no_mangle)]
250pub unsafe extern "C" fn wasmtime_anyref_clone(
251 _cx: WasmtimeStoreContextMut<'_>,
252 anyref: Option<&wasmtime_anyref_t>,
253 out: &mut MaybeUninit<wasmtime_anyref_t>,
254) {
255 let anyref = anyref.and_then(|a| a.as_wasmtime());
256 crate::initialize(out, anyref.into());
257}
258
259#[unsafe(no_mangle)]
260pub unsafe extern "C" fn wasmtime_anyref_unroot(
261 _cx: WasmtimeStoreContextMut<'_>,
262 val: Option<&mut MaybeUninit<wasmtime_anyref_t>>,
263) {
264 if let Some(val) = val.and_then(|v| v.assume_init_read().from_wasmtime()) {
265 drop(val);
266 }
267}
268
269#[unsafe(no_mangle)]
270pub unsafe extern "C" fn wasmtime_anyref_to_raw(
271 cx: WasmtimeStoreContextMut<'_>,
272 val: Option<&wasmtime_anyref_t>,
273) -> u32 {
274 val.and_then(|v| v.as_wasmtime())
275 .and_then(|e| e.to_raw(cx).ok())
276 .unwrap_or_default()
277}
278
279#[unsafe(no_mangle)]
280pub unsafe extern "C" fn wasmtime_anyref_from_raw(
281 cx: WasmtimeStoreContextMut<'_>,
282 raw: u32,
283 val: &mut MaybeUninit<wasmtime_anyref_t>,
284) {
285 let mut scope = RootScope::new(cx);
286 let anyref =
287 AnyRef::from_raw(&mut scope, raw).map(|a| a.to_owned_rooted(&mut scope).expect("in scope"));
288 crate::initialize(val, anyref.into());
289}
290
291#[unsafe(no_mangle)]
292pub extern "C" fn wasmtime_anyref_from_i31(
293 cx: WasmtimeStoreContextMut<'_>,
294 val: u32,
295 out: &mut MaybeUninit<wasmtime_anyref_t>,
296) {
297 let mut scope = RootScope::new(cx);
298 let anyref = AnyRef::from_i31(&mut scope, I31::wrapping_u32(val));
299 let anyref = anyref.to_owned_rooted(&mut scope).expect("in scope");
300 crate::initialize(out, Some(anyref).into())
301}
302
303#[unsafe(no_mangle)]
304pub unsafe extern "C" fn wasmtime_anyref_i31_get_u(
305 cx: WasmtimeStoreContextMut<'_>,
306 anyref: Option<&wasmtime_anyref_t>,
307 dst: &mut MaybeUninit<u32>,
308) -> bool {
309 match anyref.and_then(|a| a.as_wasmtime()) {
310 Some(anyref) if anyref.is_i31(&cx).expect("OwnedRooted always in scope") => {
311 let val = anyref
312 .unwrap_i31(&cx)
313 .expect("OwnedRooted always in scope")
314 .get_u32();
315 crate::initialize(dst, val);
316 true
317 }
318 _ => false,
319 }
320}
321
322#[unsafe(no_mangle)]
323pub unsafe extern "C" fn wasmtime_anyref_i31_get_s(
324 cx: WasmtimeStoreContextMut<'_>,
325 anyref: Option<&wasmtime_anyref_t>,
326 dst: &mut MaybeUninit<i32>,
327) -> bool {
328 match anyref.and_then(|a| a.as_wasmtime()) {
329 Some(anyref) if anyref.is_i31(&cx).expect("OwnedRooted always in scope") => {
330 let val = anyref
331 .unwrap_i31(&cx)
332 .expect("OwnedRooted always in scope")
333 .get_i32();
334 crate::initialize(dst, val);
335 true
336 }
337 _ => false,
338 }
339}
340
341#[unsafe(no_mangle)]
342pub extern "C" fn wasmtime_externref_new(
343 cx: WasmtimeStoreContextMut<'_>,
344 data: *mut c_void,
345 finalizer: Option<extern "C" fn(*mut c_void)>,
346 out: &mut MaybeUninit<wasmtime_externref_t>,
347) -> bool {
348 let mut scope = RootScope::new(cx);
349 let e = match ExternRef::new(&mut scope, crate::ForeignData { data, finalizer }) {
350 Ok(e) => e,
351 Err(_) => return false,
352 };
353 let e = e.to_owned_rooted(&mut scope).expect("in scope");
354 crate::initialize(out, Some(e).into());
355 true
356}
357
358#[unsafe(no_mangle)]
359pub unsafe extern "C" fn wasmtime_externref_data(
360 cx: WasmtimeStoreContextMut<'_>,
361 externref: Option<&wasmtime_externref_t>,
362) -> *mut c_void {
363 externref
364 .and_then(|e| e.as_wasmtime())
365 .and_then(|e| {
366 let data = e.data(cx).ok()??;
367 Some(data.downcast_ref::<crate::ForeignData>().unwrap().data)
368 })
369 .unwrap_or(ptr::null_mut())
370}
371
372#[unsafe(no_mangle)]
373pub unsafe extern "C" fn wasmtime_externref_clone(
374 _cx: WasmtimeStoreContextMut<'_>,
375 externref: Option<&wasmtime_externref_t>,
376 out: &mut MaybeUninit<wasmtime_externref_t>,
377) {
378 let externref = externref.and_then(|e| e.as_wasmtime());
379 crate::initialize(out, externref.into());
380}
381
382#[unsafe(no_mangle)]
383pub unsafe extern "C" fn wasmtime_externref_unroot(
384 _cx: WasmtimeStoreContextMut<'_>,
385 val: Option<&mut MaybeUninit<wasmtime_externref_t>>,
386) {
387 if let Some(val) = val.and_then(|v| v.assume_init_read().from_wasmtime()) {
388 drop(val);
389 }
390}
391
392#[unsafe(no_mangle)]
393pub unsafe extern "C" fn wasmtime_externref_to_raw(
394 cx: WasmtimeStoreContextMut<'_>,
395 val: Option<&wasmtime_externref_t>,
396) -> u32 {
397 val.and_then(|e| e.as_wasmtime())
398 .and_then(|e| e.to_raw(cx).ok())
399 .unwrap_or_default()
400}
401
402#[unsafe(no_mangle)]
403pub unsafe extern "C" fn wasmtime_externref_from_raw(
404 cx: WasmtimeStoreContextMut<'_>,
405 raw: u32,
406 val: &mut MaybeUninit<wasmtime_externref_t>,
407) {
408 let mut scope = RootScope::new(cx);
409 let rooted = ExternRef::from_raw(&mut scope, raw)
410 .map(|e| e.to_owned_rooted(&mut scope).expect("in scope"));
411 crate::initialize(val, rooted.into());
412}