1use crate::{abort, WasmtimeStoreContextMut};
2use std::{mem::MaybeUninit, num::NonZeroU64, os::raw::c_void, ptr};
3use wasmtime::{AnyRef, ExternRef, ManuallyRooted, Ref, RootScope, Val, I31};
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 }
200
201 impl $c {
202 pub unsafe fn as_wasmtime(&self) -> Option<ManuallyRooted<$wasmtime>> {
203 let store_id = NonZeroU64::new(self.store_id)?;
204 Some(ManuallyRooted::from_raw_parts_for_c_api(
205 store_id, self.a, self.b,
206 ))
207 }
208 }
209
210 impl From<Option<ManuallyRooted<$wasmtime>>> for $c {
211 fn from(rooted: Option<ManuallyRooted<$wasmtime>>) -> $c {
212 let mut ret = $c {
213 store_id: 0,
214 a: 0,
215 b: 0,
216 };
217 if let Some(rooted) = rooted {
218 let (store_id, a, b) = rooted.into_parts_for_c_api();
219 ret.store_id = store_id.get();
220 ret.a = a;
221 ret.b = b;
222 }
223 ret
224 }
225 }
226 };
227}
228
229ref_wrapper!(AnyRef => wasmtime_anyref_t);
230ref_wrapper!(ExternRef => wasmtime_externref_t);
231
232#[unsafe(no_mangle)]
233pub unsafe extern "C" fn wasmtime_anyref_clone(
234 cx: WasmtimeStoreContextMut<'_>,
235 anyref: Option<&wasmtime_anyref_t>,
236 out: &mut MaybeUninit<wasmtime_anyref_t>,
237) {
238 let anyref = anyref.and_then(|a| a.as_wasmtime()).map(|a| a.clone(cx));
239 crate::initialize(out, anyref.into());
240}
241
242#[unsafe(no_mangle)]
243pub unsafe extern "C" fn wasmtime_anyref_unroot(
244 cx: WasmtimeStoreContextMut<'_>,
245 val: Option<&mut MaybeUninit<wasmtime_anyref_t>>,
246) {
247 if let Some(val) = val.and_then(|v| v.assume_init_read().as_wasmtime()) {
248 val.unroot(cx);
249 }
250}
251
252#[unsafe(no_mangle)]
253pub unsafe extern "C" fn wasmtime_anyref_to_raw(
254 cx: WasmtimeStoreContextMut<'_>,
255 val: Option<&wasmtime_anyref_t>,
256) -> u32 {
257 val.and_then(|v| v.as_wasmtime())
258 .and_then(|e| e.to_raw(cx).ok())
259 .unwrap_or_default()
260}
261
262#[unsafe(no_mangle)]
263pub unsafe extern "C" fn wasmtime_anyref_from_raw(
264 cx: WasmtimeStoreContextMut<'_>,
265 raw: u32,
266 val: &mut MaybeUninit<wasmtime_anyref_t>,
267) {
268 let mut scope = RootScope::new(cx);
269 let anyref = AnyRef::from_raw(&mut scope, raw)
270 .map(|a| a.to_manually_rooted(&mut scope).expect("in scope"));
271 crate::initialize(val, anyref.into());
272}
273
274#[unsafe(no_mangle)]
275pub extern "C" fn wasmtime_anyref_from_i31(
276 cx: WasmtimeStoreContextMut<'_>,
277 val: u32,
278 out: &mut MaybeUninit<wasmtime_anyref_t>,
279) {
280 let mut scope = RootScope::new(cx);
281 let anyref = AnyRef::from_i31(&mut scope, I31::wrapping_u32(val));
282 let anyref = anyref.to_manually_rooted(&mut scope).expect("in scope");
283 crate::initialize(out, Some(anyref).into())
284}
285
286#[unsafe(no_mangle)]
287pub unsafe extern "C" fn wasmtime_anyref_i31_get_u(
288 cx: WasmtimeStoreContextMut<'_>,
289 anyref: Option<&wasmtime_anyref_t>,
290 dst: &mut MaybeUninit<u32>,
291) -> bool {
292 match anyref.and_then(|a| a.as_wasmtime()) {
293 Some(anyref) if anyref.is_i31(&cx).expect("ManuallyRooted always in scope") => {
294 let val = anyref
295 .unwrap_i31(&cx)
296 .expect("ManuallyRooted always in scope")
297 .get_u32();
298 crate::initialize(dst, val);
299 true
300 }
301 _ => false,
302 }
303}
304
305#[unsafe(no_mangle)]
306pub unsafe extern "C" fn wasmtime_anyref_i31_get_s(
307 cx: WasmtimeStoreContextMut<'_>,
308 anyref: Option<&wasmtime_anyref_t>,
309 dst: &mut MaybeUninit<i32>,
310) -> bool {
311 match anyref.and_then(|a| a.as_wasmtime()) {
312 Some(anyref) if anyref.is_i31(&cx).expect("ManuallyRooted always in scope") => {
313 let val = anyref
314 .unwrap_i31(&cx)
315 .expect("ManuallyRooted always in scope")
316 .get_i32();
317 crate::initialize(dst, val);
318 true
319 }
320 _ => false,
321 }
322}
323
324#[unsafe(no_mangle)]
325pub extern "C" fn wasmtime_externref_new(
326 cx: WasmtimeStoreContextMut<'_>,
327 data: *mut c_void,
328 finalizer: Option<extern "C" fn(*mut c_void)>,
329 out: &mut MaybeUninit<wasmtime_externref_t>,
330) -> bool {
331 let mut scope = RootScope::new(cx);
332 let e = match ExternRef::new(&mut scope, crate::ForeignData { data, finalizer }) {
333 Ok(e) => e,
334 Err(_) => return false,
335 };
336 let e = e.to_manually_rooted(&mut scope).expect("in scope");
337 crate::initialize(out, Some(e).into());
338 true
339}
340
341#[unsafe(no_mangle)]
342pub unsafe extern "C" fn wasmtime_externref_data(
343 cx: WasmtimeStoreContextMut<'_>,
344 externref: Option<&wasmtime_externref_t>,
345) -> *mut c_void {
346 externref
347 .and_then(|e| e.as_wasmtime())
348 .and_then(|e| {
349 let data = e.data(cx).ok()??;
350 Some(data.downcast_ref::<crate::ForeignData>().unwrap().data)
351 })
352 .unwrap_or(ptr::null_mut())
353}
354
355#[unsafe(no_mangle)]
356pub unsafe extern "C" fn wasmtime_externref_clone(
357 cx: WasmtimeStoreContextMut<'_>,
358 externref: Option<&wasmtime_externref_t>,
359 out: &mut MaybeUninit<wasmtime_externref_t>,
360) {
361 let externref = externref.and_then(|e| e.as_wasmtime()).map(|e| e.clone(cx));
362 crate::initialize(out, externref.into());
363}
364
365#[unsafe(no_mangle)]
366pub unsafe extern "C" fn wasmtime_externref_unroot(
367 cx: WasmtimeStoreContextMut<'_>,
368 val: Option<&mut MaybeUninit<wasmtime_externref_t>>,
369) {
370 if let Some(val) = val.and_then(|v| v.assume_init_read().as_wasmtime()) {
371 val.unroot(cx);
372 }
373}
374
375#[unsafe(no_mangle)]
376pub unsafe extern "C" fn wasmtime_externref_to_raw(
377 cx: WasmtimeStoreContextMut<'_>,
378 val: Option<&wasmtime_externref_t>,
379) -> u32 {
380 val.and_then(|e| e.as_wasmtime())
381 .and_then(|e| e.to_raw(cx).ok())
382 .unwrap_or_default()
383}
384
385#[unsafe(no_mangle)]
386pub unsafe extern "C" fn wasmtime_externref_from_raw(
387 cx: WasmtimeStoreContextMut<'_>,
388 raw: u32,
389 val: &mut MaybeUninit<wasmtime_externref_t>,
390) {
391 let mut scope = RootScope::new(cx);
392 let rooted = ExternRef::from_raw(&mut scope, raw)
393 .map(|e| e.to_manually_rooted(&mut scope).expect("in scope"));
394 crate::initialize(val, rooted.into());
395}