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