Skip to main content

wasmtime_c_api/
ref.rs

1use crate::{WasmtimeStoreContextMut, abort};
2use std::mem::{ManuallyDrop, MaybeUninit};
3use std::{num::NonZeroU64, os::raw::c_void, ptr};
4use wasmtime::{
5    AnyRef, ArrayRef, ArrayRefPre, ArrayType, EqRef, ExnRef, ExternRef, FieldType, I31, Mutability,
6    OwnedRooted, Ref, RootScope, StorageType, StructRef, StructRefPre, StructType, Val, ValType,
7};
8
9/// `*mut wasm_ref_t` is a reference type (`externref` or `funcref`), as seen by
10/// the C API. Because we do not have a uniform representation for `funcref`s
11/// and `externref`s, a `*mut wasm_ref_t` is morally a
12/// `Option<Box<Either<ExternRef, Func>>>`.
13///
14/// A null `*mut wasm_ref_t` is either a null `funcref` or a null `externref`
15/// depending on context (e.g. the table's element type that it is going into or
16/// coming out of).
17///
18/// Note: this is not `#[repr(C)]` because it is an opaque type in the header,
19/// and only ever referenced as `*mut wasm_ref_t`. This also lets us use a
20/// regular, non-`repr(C)` `enum` to define `WasmRefInner`.
21#[derive(Clone)]
22pub struct wasm_ref_t {
23    pub(crate) r: Ref,
24}
25
26wasmtime_c_api_macros::declare_own!(wasm_ref_t);
27
28impl wasm_ref_t {
29    pub(crate) fn new(r: Ref) -> Option<Box<wasm_ref_t>> {
30        if r.is_null() || !r.is_func() {
31            None
32        } else {
33            Some(Box::new(wasm_ref_t { r }))
34        }
35    }
36}
37
38pub(crate) fn ref_to_val(r: &wasm_ref_t) -> Val {
39    Val::from(r.r.clone())
40}
41
42#[unsafe(no_mangle)]
43pub extern "C" fn wasm_ref_copy(r: Option<&wasm_ref_t>) -> Option<Box<wasm_ref_t>> {
44    r.map(|r| Box::new(r.clone()))
45}
46
47#[unsafe(no_mangle)]
48pub extern "C" fn wasm_ref_same(_a: Option<&wasm_ref_t>, _b: Option<&wasm_ref_t>) -> bool {
49    // We need a store to determine whether these are the same reference or not.
50    abort("wasm_ref_same")
51}
52
53#[unsafe(no_mangle)]
54pub extern "C" fn wasm_ref_get_host_info(_ref: Option<&wasm_ref_t>) -> *mut c_void {
55    std::ptr::null_mut()
56}
57
58#[unsafe(no_mangle)]
59pub extern "C" fn wasm_ref_set_host_info(_ref: Option<&wasm_ref_t>, _info: *mut c_void) {
60    abort("wasm_ref_set_host_info")
61}
62
63#[unsafe(no_mangle)]
64pub extern "C" fn wasm_ref_set_host_info_with_finalizer(
65    _ref: Option<&wasm_ref_t>,
66    _info: *mut c_void,
67    _finalizer: Option<extern "C" fn(*mut c_void)>,
68) {
69    abort("wasm_ref_set_host_info_with_finalizer")
70}
71
72#[unsafe(no_mangle)]
73pub extern "C" fn wasm_ref_as_extern(_ref: Option<&wasm_ref_t>) -> Option<&crate::wasm_extern_t> {
74    abort("wasm_ref_as_extern")
75}
76
77#[unsafe(no_mangle)]
78pub extern "C" fn wasm_ref_as_extern_const(
79    _ref: Option<&wasm_ref_t>,
80) -> Option<&crate::wasm_extern_t> {
81    abort("wasm_ref_as_extern_const")
82}
83
84#[unsafe(no_mangle)]
85pub extern "C" fn wasm_ref_as_foreign(_ref: Option<&wasm_ref_t>) -> Option<&crate::wasm_foreign_t> {
86    abort("wasm_ref_as_foreign")
87}
88
89#[unsafe(no_mangle)]
90pub extern "C" fn wasm_ref_as_foreign_const(
91    _ref: Option<&wasm_ref_t>,
92) -> Option<&crate::wasm_foreign_t> {
93    abort("wasm_ref_as_foreign_const")
94}
95
96#[unsafe(no_mangle)]
97pub extern "C" fn wasm_ref_as_func(_ref: Option<&wasm_ref_t>) -> Option<&crate::wasm_func_t> {
98    abort("wasm_ref_as_func")
99}
100
101#[unsafe(no_mangle)]
102pub extern "C" fn wasm_ref_as_func_const(_ref: Option<&wasm_ref_t>) -> Option<&crate::wasm_func_t> {
103    abort("wasm_ref_as_func_const")
104}
105
106#[unsafe(no_mangle)]
107pub extern "C" fn wasm_ref_as_global(_ref: Option<&wasm_ref_t>) -> Option<&crate::wasm_global_t> {
108    abort("wasm_ref_as_global")
109}
110
111#[unsafe(no_mangle)]
112pub extern "C" fn wasm_ref_as_global_const(
113    _ref: Option<&wasm_ref_t>,
114) -> Option<&crate::wasm_global_t> {
115    abort("wasm_ref_as_global_const")
116}
117
118#[unsafe(no_mangle)]
119pub extern "C" fn wasm_ref_as_instance(
120    _ref: Option<&wasm_ref_t>,
121) -> Option<&crate::wasm_instance_t> {
122    abort("wasm_ref_as_instance")
123}
124
125#[unsafe(no_mangle)]
126pub extern "C" fn wasm_ref_as_instance_const(
127    _ref: Option<&wasm_ref_t>,
128) -> Option<&crate::wasm_instance_t> {
129    abort("wasm_ref_as_instance_const")
130}
131
132#[unsafe(no_mangle)]
133pub extern "C" fn wasm_ref_as_memory(_ref: Option<&wasm_ref_t>) -> Option<&crate::wasm_memory_t> {
134    abort("wasm_ref_as_memory")
135}
136
137#[unsafe(no_mangle)]
138pub extern "C" fn wasm_ref_as_memory_const(
139    _ref: Option<&wasm_ref_t>,
140) -> Option<&crate::wasm_memory_t> {
141    abort("wasm_ref_as_memory_const")
142}
143
144#[unsafe(no_mangle)]
145pub extern "C" fn wasm_ref_as_module(_ref: Option<&wasm_ref_t>) -> Option<&crate::wasm_module_t> {
146    abort("wasm_ref_as_module")
147}
148
149#[unsafe(no_mangle)]
150pub extern "C" fn wasm_ref_as_module_const(
151    _ref: Option<&wasm_ref_t>,
152) -> Option<&crate::wasm_module_t> {
153    abort("wasm_ref_as_module_const")
154}
155
156#[unsafe(no_mangle)]
157pub extern "C" fn wasm_ref_as_table(_ref: Option<&wasm_ref_t>) -> Option<&crate::wasm_table_t> {
158    abort("wasm_ref_as_table")
159}
160
161#[unsafe(no_mangle)]
162pub extern "C" fn wasm_ref_as_table_const(
163    _ref: Option<&wasm_ref_t>,
164) -> Option<&crate::wasm_table_t> {
165    abort("wasm_ref_as_table_const")
166}
167
168#[unsafe(no_mangle)]
169pub extern "C" fn wasm_ref_as_trap(_ref: Option<&wasm_ref_t>) -> Option<&crate::wasm_trap_t> {
170    abort("wasm_ref_as_trap")
171}
172
173#[unsafe(no_mangle)]
174pub extern "C" fn wasm_ref_as_trap_const(_ref: Option<&wasm_ref_t>) -> Option<&crate::wasm_trap_t> {
175    abort("wasm_ref_as_trap_const")
176}
177
178#[derive(Clone)]
179#[repr(C)]
180pub struct wasm_foreign_t {}
181
182wasmtime_c_api_macros::declare_ref!(wasm_foreign_t);
183
184#[unsafe(no_mangle)]
185pub extern "C" fn wasm_foreign_new(_store: &crate::wasm_store_t) -> Box<wasm_foreign_t> {
186    abort("wasm_foreign_new")
187}
188
189/// C-API representation of `anyref`.
190///
191/// This represented differently in the C API from the header to handle how
192/// this is dispatched internally. Null anyref values are represented with a
193/// `store_id` of zero, and otherwise the `rooted` field is valid.
194///
195/// Note that this relies on the Wasmtime definition of `OwnedRooted` to have
196/// a 64-bit store_id first.
197macro_rules! ref_wrapper {
198    ($wasmtime:ident => $c:ident) => {
199        pub struct $c {
200            store_id: u64,
201            a: u32,
202            b: u32,
203            c: *const (),
204        }
205
206        impl $c {
207            pub unsafe fn as_wasmtime(&self) -> Option<OwnedRooted<$wasmtime>> {
208                let store_id = NonZeroU64::new(self.store_id)?;
209                Some(OwnedRooted::from_borrowed_raw_parts_for_c_api(
210                    store_id, self.a, self.b, self.c,
211                ))
212            }
213
214            pub unsafe fn into_wasmtime(self) -> Option<OwnedRooted<$wasmtime>> {
215                ManuallyDrop::new(self).to_owned()
216            }
217
218            unsafe fn to_owned(&self) -> Option<OwnedRooted<$wasmtime>> {
219                let store_id = NonZeroU64::new(self.store_id)?;
220                Some(OwnedRooted::from_owned_raw_parts_for_c_api(
221                    store_id, self.a, self.b, self.c,
222                ))
223            }
224        }
225
226        impl Drop for $c {
227            fn drop(&mut self) {
228                unsafe {
229                    let _ = self.to_owned();
230                }
231            }
232        }
233
234        impl From<Option<OwnedRooted<$wasmtime>>> for $c {
235            fn from(rooted: Option<OwnedRooted<$wasmtime>>) -> $c {
236                let mut ret = $c {
237                    store_id: 0,
238                    a: 0,
239                    b: 0,
240                    c: core::ptr::null(),
241                };
242                if let Some(rooted) = rooted {
243                    let (store_id, a, b, c) = rooted.into_parts_for_c_api();
244                    ret.store_id = store_id.get();
245                    ret.a = a;
246                    ret.b = b;
247                    ret.c = c;
248                }
249                ret
250            }
251        }
252
253        impl From<OwnedRooted<$wasmtime>> for $c {
254            fn from(rooted: OwnedRooted<$wasmtime>) -> $c {
255                Self::from(Some(rooted))
256            }
257        }
258
259        // SAFETY: The `*const ()` comes from (and is converted back
260        // into) an `Arc<()>`, and is only accessed as such, so this
261        // type is both Send and Sync. These constraints are necessary
262        // in the async machinery in this crate.
263        unsafe impl Send for $c {}
264        unsafe impl Sync for $c {}
265    };
266}
267
268ref_wrapper!(AnyRef => wasmtime_anyref_t);
269ref_wrapper!(ExternRef => wasmtime_externref_t);
270ref_wrapper!(EqRef => wasmtime_eqref_t);
271ref_wrapper!(StructRef => wasmtime_structref_t);
272ref_wrapper!(ExnRef => wasmtime_exnref_t);
273
274// Opaque types for struct type and struct ref pre-allocator
275pub struct wasmtime_struct_type_t {
276    ty: StructType,
277}
278wasmtime_c_api_macros::declare_own!(wasmtime_struct_type_t);
279
280pub struct wasmtime_struct_ref_pre_t {
281    pre: StructRefPre,
282}
283wasmtime_c_api_macros::declare_own!(wasmtime_struct_ref_pre_t);
284
285ref_wrapper!(ArrayRef => wasmtime_arrayref_t);
286
287pub struct wasmtime_array_type_t {
288    ty: ArrayType,
289}
290wasmtime_c_api_macros::declare_own!(wasmtime_array_type_t);
291
292pub struct wasmtime_array_ref_pre_t {
293    pre: ArrayRefPre,
294}
295wasmtime_c_api_macros::declare_own!(wasmtime_array_ref_pre_t);
296
297#[unsafe(no_mangle)]
298pub unsafe extern "C" fn wasmtime_anyref_clone(
299    anyref: Option<&wasmtime_anyref_t>,
300    out: &mut MaybeUninit<wasmtime_anyref_t>,
301) {
302    let anyref = anyref.and_then(|a| a.as_wasmtime());
303    crate::initialize(out, anyref.into());
304}
305
306#[unsafe(no_mangle)]
307pub unsafe extern "C" fn wasmtime_anyref_unroot(val: Option<&mut ManuallyDrop<wasmtime_anyref_t>>) {
308    if let Some(val) = val {
309        unsafe {
310            ManuallyDrop::drop(val);
311        }
312    }
313}
314
315#[unsafe(no_mangle)]
316pub unsafe extern "C" fn wasmtime_anyref_to_raw(
317    cx: WasmtimeStoreContextMut<'_>,
318    val: Option<&wasmtime_anyref_t>,
319) -> u32 {
320    val.and_then(|v| v.as_wasmtime())
321        .and_then(|e| e.to_raw(cx).ok())
322        .unwrap_or_default()
323}
324
325#[unsafe(no_mangle)]
326pub unsafe extern "C" fn wasmtime_anyref_from_raw(
327    cx: WasmtimeStoreContextMut<'_>,
328    raw: u32,
329    val: &mut MaybeUninit<wasmtime_anyref_t>,
330) {
331    let mut scope = RootScope::new(cx);
332    let anyref =
333        AnyRef::from_raw(&mut scope, raw).map(|a| a.to_owned_rooted(&mut scope).expect("in scope"));
334    crate::initialize(val, anyref.into());
335}
336
337#[unsafe(no_mangle)]
338pub extern "C" fn wasmtime_anyref_from_i31(
339    cx: WasmtimeStoreContextMut<'_>,
340    val: u32,
341    out: &mut MaybeUninit<wasmtime_anyref_t>,
342) {
343    let mut scope = RootScope::new(cx);
344    let anyref = AnyRef::from_i31(&mut scope, I31::wrapping_u32(val));
345    let anyref = anyref.to_owned_rooted(&mut scope).expect("in scope");
346    crate::initialize(out, Some(anyref).into())
347}
348
349#[unsafe(no_mangle)]
350pub unsafe extern "C" fn wasmtime_anyref_is_i31(
351    cx: WasmtimeStoreContextMut<'_>,
352    anyref: Option<&wasmtime_anyref_t>,
353) -> bool {
354    match anyref.and_then(|a| a.as_wasmtime()) {
355        Some(anyref) => anyref.is_i31(&cx).expect("OwnedRooted always in scope"),
356        None => false,
357    }
358}
359
360#[unsafe(no_mangle)]
361pub unsafe extern "C" fn wasmtime_anyref_i31_get_u(
362    cx: WasmtimeStoreContextMut<'_>,
363    anyref: Option<&wasmtime_anyref_t>,
364    dst: &mut MaybeUninit<u32>,
365) -> bool {
366    match anyref.and_then(|a| a.as_wasmtime()) {
367        Some(anyref) if anyref.is_i31(&cx).expect("OwnedRooted always in scope") => {
368            let val = anyref
369                .unwrap_i31(&cx)
370                .expect("OwnedRooted always in scope")
371                .get_u32();
372            crate::initialize(dst, val);
373            true
374        }
375        _ => false,
376    }
377}
378
379#[unsafe(no_mangle)]
380pub unsafe extern "C" fn wasmtime_anyref_i31_get_s(
381    cx: WasmtimeStoreContextMut<'_>,
382    anyref: Option<&wasmtime_anyref_t>,
383    dst: &mut MaybeUninit<i32>,
384) -> bool {
385    match anyref.and_then(|a| a.as_wasmtime()) {
386        Some(anyref) if anyref.is_i31(&cx).expect("OwnedRooted always in scope") => {
387            let val = anyref
388                .unwrap_i31(&cx)
389                .expect("OwnedRooted always in scope")
390                .get_i32();
391            crate::initialize(dst, val);
392            true
393        }
394        _ => false,
395    }
396}
397
398#[unsafe(no_mangle)]
399pub extern "C" fn wasmtime_externref_new(
400    cx: WasmtimeStoreContextMut<'_>,
401    data: *mut c_void,
402    finalizer: Option<extern "C" fn(*mut c_void)>,
403    out: &mut MaybeUninit<wasmtime_externref_t>,
404) -> bool {
405    let mut scope = RootScope::new(cx);
406    let e = match ExternRef::new(&mut scope, crate::ForeignData { data, finalizer }) {
407        Ok(e) => e,
408        Err(_) => return false,
409    };
410    let e = e.to_owned_rooted(&mut scope).expect("in scope");
411    crate::initialize(out, Some(e).into());
412    true
413}
414
415#[unsafe(no_mangle)]
416pub unsafe extern "C" fn wasmtime_externref_data(
417    cx: WasmtimeStoreContextMut<'_>,
418    externref: Option<&wasmtime_externref_t>,
419) -> *mut c_void {
420    externref
421        .and_then(|e| e.as_wasmtime())
422        .and_then(|e| {
423            let data = e.data(cx).ok()??;
424            Some(data.downcast_ref::<crate::ForeignData>().unwrap().data)
425        })
426        .unwrap_or(ptr::null_mut())
427}
428
429#[unsafe(no_mangle)]
430pub unsafe extern "C" fn wasmtime_externref_clone(
431    externref: Option<&wasmtime_externref_t>,
432    out: &mut MaybeUninit<wasmtime_externref_t>,
433) {
434    let externref = externref.and_then(|e| e.as_wasmtime());
435    crate::initialize(out, externref.into());
436}
437
438#[unsafe(no_mangle)]
439pub unsafe extern "C" fn wasmtime_externref_unroot(
440    val: Option<&mut ManuallyDrop<wasmtime_externref_t>>,
441) {
442    if let Some(val) = val {
443        unsafe {
444            ManuallyDrop::drop(val);
445        }
446    }
447}
448
449#[unsafe(no_mangle)]
450pub unsafe extern "C" fn wasmtime_externref_to_raw(
451    cx: WasmtimeStoreContextMut<'_>,
452    val: Option<&wasmtime_externref_t>,
453) -> u32 {
454    val.and_then(|e| e.as_wasmtime())
455        .and_then(|e| e.to_raw(cx).ok())
456        .unwrap_or_default()
457}
458
459#[unsafe(no_mangle)]
460pub unsafe extern "C" fn wasmtime_externref_from_raw(
461    cx: WasmtimeStoreContextMut<'_>,
462    raw: u32,
463    val: &mut MaybeUninit<wasmtime_externref_t>,
464) {
465    let mut scope = RootScope::new(cx);
466    let rooted = ExternRef::from_raw(&mut scope, raw)
467        .map(|e| e.to_owned_rooted(&mut scope).expect("in scope"));
468    crate::initialize(val, rooted.into());
469}
470
471#[unsafe(no_mangle)]
472pub unsafe extern "C" fn wasmtime_exnref_clone(
473    exnref: Option<&wasmtime_exnref_t>,
474    out: &mut MaybeUninit<wasmtime_exnref_t>,
475) {
476    let exnref = exnref.and_then(|e| e.as_wasmtime());
477    crate::initialize(out, exnref.into());
478}
479
480#[unsafe(no_mangle)]
481pub unsafe extern "C" fn wasmtime_exnref_unroot(val: Option<&mut ManuallyDrop<wasmtime_exnref_t>>) {
482    if let Some(val) = val {
483        unsafe {
484            ManuallyDrop::drop(val);
485        }
486    }
487}
488
489#[unsafe(no_mangle)]
490pub unsafe extern "C" fn wasmtime_eqref_clone(
491    eqref: Option<&wasmtime_eqref_t>,
492    out: &mut MaybeUninit<wasmtime_eqref_t>,
493) {
494    let eqref = eqref.and_then(|e| e.as_wasmtime());
495    crate::initialize(out, eqref.into());
496}
497
498#[unsafe(no_mangle)]
499pub unsafe extern "C" fn wasmtime_eqref_unroot(val: Option<&mut ManuallyDrop<wasmtime_eqref_t>>) {
500    if let Some(val) = val {
501        unsafe {
502            ManuallyDrop::drop(val);
503        }
504    }
505}
506
507#[unsafe(no_mangle)]
508pub unsafe extern "C" fn wasmtime_eqref_to_anyref(
509    eqref: Option<&wasmtime_eqref_t>,
510    out: &mut MaybeUninit<wasmtime_anyref_t>,
511) {
512    let anyref = eqref.and_then(|e| e.as_wasmtime()).map(|e| e.to_anyref());
513    crate::initialize(out, anyref.into());
514}
515
516#[unsafe(no_mangle)]
517pub extern "C" fn wasmtime_eqref_from_i31(
518    cx: WasmtimeStoreContextMut<'_>,
519    val: u32,
520    out: &mut MaybeUninit<wasmtime_eqref_t>,
521) {
522    let mut scope = RootScope::new(cx);
523    let eqref = EqRef::from_i31(&mut scope, I31::wrapping_u32(val));
524    let eqref = eqref.to_owned_rooted(&mut scope).expect("in scope");
525    crate::initialize(out, Some(eqref).into())
526}
527
528#[unsafe(no_mangle)]
529pub unsafe extern "C" fn wasmtime_eqref_is_i31(
530    cx: WasmtimeStoreContextMut<'_>,
531    eqref: Option<&wasmtime_eqref_t>,
532) -> bool {
533    match eqref.and_then(|e| e.as_wasmtime()) {
534        Some(eqref) => eqref.is_i31(&cx).expect("OwnedRooted always in scope"),
535        None => false,
536    }
537}
538
539#[unsafe(no_mangle)]
540pub unsafe extern "C" fn wasmtime_eqref_i31_get_u(
541    cx: WasmtimeStoreContextMut<'_>,
542    eqref: Option<&wasmtime_eqref_t>,
543    dst: &mut MaybeUninit<u32>,
544) -> bool {
545    let mut scope = RootScope::new(cx);
546    if let Some(eqref) = eqref.and_then(|e| e.as_wasmtime()) {
547        if let Some(val) = eqref.as_i31(&mut scope).expect("in scope") {
548            crate::initialize(dst, val.get_u32());
549            return true;
550        }
551    }
552    false
553}
554
555#[unsafe(no_mangle)]
556pub unsafe extern "C" fn wasmtime_eqref_i31_get_s(
557    cx: WasmtimeStoreContextMut<'_>,
558    eqref: Option<&wasmtime_eqref_t>,
559    dst: &mut MaybeUninit<i32>,
560) -> bool {
561    let mut scope = RootScope::new(cx);
562    if let Some(eqref) = eqref.and_then(|e| e.as_wasmtime()) {
563        if let Some(val) = eqref.as_i31(&mut scope).expect("in scope") {
564            crate::initialize(dst, val.get_i32());
565            return true;
566        }
567    }
568    false
569}
570
571pub type wasmtime_storage_kind_t = u8;
572pub const WASMTIME_STORAGE_KIND_I8: wasmtime_storage_kind_t = 9;
573pub const WASMTIME_STORAGE_KIND_I16: wasmtime_storage_kind_t = 10;
574
575#[repr(C)]
576pub struct wasmtime_field_type_t {
577    pub kind: wasmtime_storage_kind_t,
578    pub mutable_: bool,
579}
580
581fn field_type_from_c(ft: &wasmtime_field_type_t) -> FieldType {
582    let mutability = if ft.mutable_ {
583        Mutability::Var
584    } else {
585        Mutability::Const
586    };
587    let storage = match ft.kind {
588        WASMTIME_STORAGE_KIND_I8 => StorageType::I8,
589        WASMTIME_STORAGE_KIND_I16 => StorageType::I16,
590        crate::WASMTIME_I32 => StorageType::ValType(ValType::I32),
591        crate::WASMTIME_I64 => StorageType::ValType(ValType::I64),
592        crate::WASMTIME_F32 => StorageType::ValType(ValType::F32),
593        crate::WASMTIME_F64 => StorageType::ValType(ValType::F64),
594        crate::WASMTIME_V128 => StorageType::ValType(ValType::V128),
595        crate::WASMTIME_FUNCREF => StorageType::ValType(ValType::FUNCREF),
596        crate::WASMTIME_EXTERNREF => StorageType::ValType(ValType::EXTERNREF),
597        crate::WASMTIME_ANYREF => StorageType::ValType(ValType::ANYREF),
598        crate::WASMTIME_EXNREF => StorageType::ValType(ValType::EXNREF),
599        other => panic!("unknown wasmtime_storage_kind_t: {other}"),
600    };
601    FieldType::new(mutability, storage)
602}
603
604#[unsafe(no_mangle)]
605pub extern "C" fn wasmtime_struct_type_new(
606    engine: &crate::wasm_engine_t,
607    fields: *const wasmtime_field_type_t,
608    nfields: usize,
609) -> Box<wasmtime_struct_type_t> {
610    let fields = if nfields == 0 {
611        &[]
612    } else {
613        unsafe { std::slice::from_raw_parts(fields, nfields) }
614    };
615    let field_types: Vec<FieldType> = fields.iter().map(field_type_from_c).collect();
616    let ty = StructType::new(&engine.engine, field_types).expect("failed to create struct type");
617    Box::new(wasmtime_struct_type_t { ty })
618}
619
620#[unsafe(no_mangle)]
621pub extern "C" fn wasmtime_struct_ref_pre_new(
622    cx: WasmtimeStoreContextMut<'_>,
623    ty: &wasmtime_struct_type_t,
624) -> Box<wasmtime_struct_ref_pre_t> {
625    let pre = StructRefPre::new(cx, ty.ty.clone());
626    Box::new(wasmtime_struct_ref_pre_t { pre })
627}
628
629#[unsafe(no_mangle)]
630pub unsafe extern "C" fn wasmtime_structref_new(
631    mut cx: WasmtimeStoreContextMut<'_>,
632    pre: &wasmtime_struct_ref_pre_t,
633    fields: *const crate::wasmtime_val_t,
634    nfields: usize,
635    out: &mut MaybeUninit<wasmtime_structref_t>,
636) -> Option<Box<crate::wasmtime_error_t>> {
637    let c_fields = if nfields == 0 {
638        &[]
639    } else {
640        std::slice::from_raw_parts(fields, nfields)
641    };
642    let mut scope = RootScope::new(&mut cx);
643    let vals: Vec<Val> = c_fields.iter().map(|v| v.to_val(&mut scope)).collect();
644    match StructRef::new(&mut scope, &pre.pre, &vals) {
645        Ok(structref) => {
646            let owned = structref
647                .to_owned_rooted(&mut scope)
648                .expect("just allocated");
649            crate::initialize(out, Some(owned).into());
650            None
651        }
652        Err(e) => {
653            crate::initialize(out, None::<OwnedRooted<StructRef>>.into());
654            Some(Box::new(e.into()))
655        }
656    }
657}
658
659#[unsafe(no_mangle)]
660pub unsafe extern "C" fn wasmtime_structref_clone(
661    structref: Option<&wasmtime_structref_t>,
662    out: &mut MaybeUninit<wasmtime_structref_t>,
663) {
664    let structref = structref.and_then(|s| s.as_wasmtime());
665    crate::initialize(out, structref.into());
666}
667
668#[unsafe(no_mangle)]
669pub unsafe extern "C" fn wasmtime_structref_unroot(
670    structref: Option<&mut ManuallyDrop<wasmtime_structref_t>>,
671) {
672    if let Some(structref) = structref {
673        ManuallyDrop::drop(structref);
674    }
675}
676
677#[unsafe(no_mangle)]
678pub unsafe extern "C" fn wasmtime_structref_to_anyref(
679    structref: Option<&wasmtime_structref_t>,
680    out: &mut MaybeUninit<wasmtime_anyref_t>,
681) {
682    let anyref = structref
683        .and_then(|s| s.as_wasmtime())
684        .map(|s| s.to_anyref());
685    crate::initialize(out, anyref.into());
686}
687
688#[unsafe(no_mangle)]
689pub unsafe extern "C" fn wasmtime_structref_to_eqref(
690    structref: Option<&wasmtime_structref_t>,
691    out: &mut MaybeUninit<wasmtime_eqref_t>,
692) {
693    let eqref = structref
694        .and_then(|s| s.as_wasmtime())
695        .map(|s| s.to_eqref());
696    crate::initialize(out, eqref.into());
697}
698
699#[unsafe(no_mangle)]
700pub unsafe extern "C" fn wasmtime_structref_field(
701    mut cx: WasmtimeStoreContextMut<'_>,
702    structref: Option<&wasmtime_structref_t>,
703    index: usize,
704    out: &mut MaybeUninit<crate::wasmtime_val_t>,
705) -> Option<Box<crate::wasmtime_error_t>> {
706    let structref = structref
707        .and_then(|s| s.as_wasmtime())
708        .expect("non-null structref required");
709    let mut scope = RootScope::new(&mut cx);
710    let rooted = structref.to_rooted(&mut scope);
711    match rooted.field(&mut scope, index) {
712        Ok(val) => {
713            let c_val = crate::wasmtime_val_t::from_val(&mut scope, val);
714            crate::initialize(out, c_val);
715            None
716        }
717        Err(e) => Some(Box::new(e.into())),
718    }
719}
720
721#[unsafe(no_mangle)]
722pub unsafe extern "C" fn wasmtime_structref_set_field(
723    mut cx: WasmtimeStoreContextMut<'_>,
724    structref: Option<&wasmtime_structref_t>,
725    index: usize,
726    val: &crate::wasmtime_val_t,
727) -> Option<Box<crate::wasmtime_error_t>> {
728    let structref = structref
729        .and_then(|s| s.as_wasmtime())
730        .expect("non-null structref required");
731    let mut scope = RootScope::new(&mut cx);
732    let rooted = structref.to_rooted(&mut scope);
733    let rust_val = val.to_val(&mut scope);
734    match rooted.set_field(&mut scope, index, rust_val) {
735        Ok(()) => None,
736        Err(e) => Some(Box::new(e.into())),
737    }
738}
739
740#[unsafe(no_mangle)]
741pub unsafe extern "C" fn wasmtime_eqref_is_struct(
742    cx: WasmtimeStoreContextMut<'_>,
743    eqref: Option<&wasmtime_eqref_t>,
744) -> bool {
745    match eqref.and_then(|e| e.as_wasmtime()) {
746        Some(eqref) => eqref.is_struct(&cx).expect("OwnedRooted always in scope"),
747        None => false,
748    }
749}
750
751#[unsafe(no_mangle)]
752pub unsafe extern "C" fn wasmtime_eqref_as_struct(
753    mut cx: WasmtimeStoreContextMut<'_>,
754    eqref: Option<&wasmtime_eqref_t>,
755    out: &mut MaybeUninit<wasmtime_structref_t>,
756) -> bool {
757    if let Some(eqref) = eqref.and_then(|e| e.as_wasmtime()) {
758        let mut scope = RootScope::new(&mut cx);
759        let rooted = eqref.to_rooted(&mut scope);
760        if let Ok(Some(structref)) = rooted.as_struct(&scope) {
761            let owned = structref.to_owned_rooted(&mut scope).expect("in scope");
762            crate::initialize(out, Some(owned).into());
763            return true;
764        }
765    }
766    crate::initialize(out, None::<OwnedRooted<StructRef>>.into());
767    false
768}
769
770#[unsafe(no_mangle)]
771pub extern "C" fn wasmtime_array_type_new(
772    engine: &crate::wasm_engine_t,
773    field: &wasmtime_field_type_t,
774) -> Box<wasmtime_array_type_t> {
775    let ft = field_type_from_c(field);
776    let ty = ArrayType::new(&engine.engine, ft);
777    Box::new(wasmtime_array_type_t { ty })
778}
779
780#[unsafe(no_mangle)]
781pub extern "C" fn wasmtime_array_ref_pre_new(
782    cx: WasmtimeStoreContextMut<'_>,
783    ty: &wasmtime_array_type_t,
784) -> Box<wasmtime_array_ref_pre_t> {
785    let pre = ArrayRefPre::new(cx, ty.ty.clone());
786    Box::new(wasmtime_array_ref_pre_t { pre })
787}
788
789#[unsafe(no_mangle)]
790pub unsafe extern "C" fn wasmtime_arrayref_new(
791    mut cx: WasmtimeStoreContextMut<'_>,
792    pre: &wasmtime_array_ref_pre_t,
793    elem: &crate::wasmtime_val_t,
794    len: u32,
795    out: &mut MaybeUninit<wasmtime_arrayref_t>,
796) -> Option<Box<crate::wasmtime_error_t>> {
797    let mut scope = RootScope::new(&mut cx);
798    let val = elem.to_val(&mut scope);
799    match ArrayRef::new(&mut scope, &pre.pre, &val, len) {
800        Ok(arrayref) => {
801            let owned = arrayref
802                .to_owned_rooted(&mut scope)
803                .expect("just allocated");
804            crate::initialize(out, Some(owned).into());
805            None
806        }
807        Err(e) => {
808            crate::initialize(out, None::<OwnedRooted<ArrayRef>>.into());
809            Some(Box::new(e.into()))
810        }
811    }
812}
813
814#[unsafe(no_mangle)]
815pub unsafe extern "C" fn wasmtime_arrayref_clone(
816    arrayref: Option<&wasmtime_arrayref_t>,
817    out: &mut MaybeUninit<wasmtime_arrayref_t>,
818) {
819    let arrayref = arrayref.and_then(|a| a.as_wasmtime());
820    crate::initialize(out, arrayref.into());
821}
822
823#[unsafe(no_mangle)]
824pub unsafe extern "C" fn wasmtime_arrayref_unroot(
825    arrayref: Option<&mut ManuallyDrop<wasmtime_arrayref_t>>,
826) {
827    if let Some(arrayref) = arrayref {
828        ManuallyDrop::drop(arrayref);
829    }
830}
831
832#[unsafe(no_mangle)]
833pub unsafe extern "C" fn wasmtime_arrayref_to_anyref(
834    arrayref: Option<&wasmtime_arrayref_t>,
835    out: &mut MaybeUninit<wasmtime_anyref_t>,
836) {
837    let anyref = arrayref
838        .and_then(|a| a.as_wasmtime())
839        .map(|a| a.to_anyref());
840    crate::initialize(out, anyref.into());
841}
842
843#[unsafe(no_mangle)]
844pub unsafe extern "C" fn wasmtime_arrayref_to_eqref(
845    arrayref: Option<&wasmtime_arrayref_t>,
846    out: &mut MaybeUninit<wasmtime_eqref_t>,
847) {
848    let eqref = arrayref.and_then(|a| a.as_wasmtime()).map(|a| a.to_eqref());
849    crate::initialize(out, eqref.into());
850}
851
852#[unsafe(no_mangle)]
853pub unsafe extern "C" fn wasmtime_arrayref_len(
854    cx: WasmtimeStoreContextMut<'_>,
855    arrayref: Option<&wasmtime_arrayref_t>,
856    out: &mut MaybeUninit<u32>,
857) -> Option<Box<crate::wasmtime_error_t>> {
858    let arrayref = arrayref
859        .and_then(|a| a.as_wasmtime())
860        .expect("non-null arrayref required");
861    match arrayref.len(&cx) {
862        Ok(len) => {
863            crate::initialize(out, len);
864            None
865        }
866        Err(e) => Some(Box::new(e.into())),
867    }
868}
869
870#[unsafe(no_mangle)]
871pub unsafe extern "C" fn wasmtime_arrayref_get(
872    mut cx: WasmtimeStoreContextMut<'_>,
873    arrayref: Option<&wasmtime_arrayref_t>,
874    index: u32,
875    out: &mut MaybeUninit<crate::wasmtime_val_t>,
876) -> Option<Box<crate::wasmtime_error_t>> {
877    let arrayref = arrayref
878        .and_then(|a| a.as_wasmtime())
879        .expect("non-null arrayref required");
880    let mut scope = RootScope::new(&mut cx);
881    let rooted = arrayref.to_rooted(&mut scope);
882    match rooted.get(&mut scope, index) {
883        Ok(val) => {
884            let c_val = crate::wasmtime_val_t::from_val(&mut scope, val);
885            crate::initialize(out, c_val);
886            None
887        }
888        Err(e) => Some(Box::new(e.into())),
889    }
890}
891
892#[unsafe(no_mangle)]
893pub unsafe extern "C" fn wasmtime_arrayref_set(
894    mut cx: WasmtimeStoreContextMut<'_>,
895    arrayref: Option<&wasmtime_arrayref_t>,
896    index: u32,
897    val: &crate::wasmtime_val_t,
898) -> Option<Box<crate::wasmtime_error_t>> {
899    let arrayref = arrayref
900        .and_then(|a| a.as_wasmtime())
901        .expect("non-null arrayref required");
902    let mut scope = RootScope::new(&mut cx);
903    let rooted = arrayref.to_rooted(&mut scope);
904    let rust_val = val.to_val(&mut scope);
905    match rooted.set(&mut scope, index, rust_val) {
906        Ok(()) => None,
907        Err(e) => Some(Box::new(e.into())),
908    }
909}
910
911#[unsafe(no_mangle)]
912pub unsafe extern "C" fn wasmtime_eqref_is_array(
913    cx: WasmtimeStoreContextMut<'_>,
914    eqref: Option<&wasmtime_eqref_t>,
915) -> bool {
916    match eqref.and_then(|e| e.as_wasmtime()) {
917        Some(eqref) => eqref.is_array(&cx).expect("OwnedRooted always in scope"),
918        None => false,
919    }
920}
921
922#[unsafe(no_mangle)]
923pub unsafe extern "C" fn wasmtime_eqref_as_array(
924    mut cx: WasmtimeStoreContextMut<'_>,
925    eqref: Option<&wasmtime_eqref_t>,
926    out: &mut MaybeUninit<wasmtime_arrayref_t>,
927) -> bool {
928    if let Some(eqref) = eqref.and_then(|e| e.as_wasmtime()) {
929        let mut scope = RootScope::new(&mut cx);
930        let rooted = eqref.to_rooted(&mut scope);
931        if let Ok(Some(arrayref)) = rooted.as_array(&scope) {
932            let owned = arrayref.to_owned_rooted(&mut scope).expect("just created");
933            crate::initialize(out, Some(owned).into());
934            return true;
935        }
936    }
937    crate::initialize(out, None::<OwnedRooted<ArrayRef>>.into());
938    false
939}
940
941#[unsafe(no_mangle)]
942pub unsafe extern "C" fn wasmtime_anyref_is_eqref(
943    cx: WasmtimeStoreContextMut<'_>,
944    anyref: Option<&wasmtime_anyref_t>,
945) -> bool {
946    match anyref.and_then(|a| a.as_wasmtime()) {
947        Some(anyref) => anyref.is_eqref(&cx).expect("OwnedRooted always in scope"),
948        None => false,
949    }
950}
951
952#[unsafe(no_mangle)]
953pub unsafe extern "C" fn wasmtime_anyref_as_eqref(
954    mut cx: WasmtimeStoreContextMut<'_>,
955    anyref: Option<&wasmtime_anyref_t>,
956    out: &mut MaybeUninit<wasmtime_eqref_t>,
957) -> bool {
958    if let Some(anyref) = anyref.and_then(|a| a.as_wasmtime()) {
959        let mut scope = RootScope::new(&mut cx);
960        let rooted = anyref.to_rooted(&mut scope);
961        if let Ok(Some(eqref)) = rooted.as_eqref(&mut scope) {
962            let owned = eqref.to_owned_rooted(&mut scope).expect("in scope");
963            crate::initialize(out, Some(owned).into());
964            return true;
965        }
966    }
967    crate::initialize(out, None::<OwnedRooted<EqRef>>.into());
968    false
969}
970
971#[unsafe(no_mangle)]
972pub unsafe extern "C" fn wasmtime_anyref_is_struct(
973    cx: WasmtimeStoreContextMut<'_>,
974    anyref: Option<&wasmtime_anyref_t>,
975) -> bool {
976    match anyref.and_then(|a| a.as_wasmtime()) {
977        Some(anyref) => anyref.is_struct(&cx).expect("OwnedRooted always in scope"),
978        None => false,
979    }
980}
981
982#[unsafe(no_mangle)]
983pub unsafe extern "C" fn wasmtime_anyref_as_struct(
984    mut cx: WasmtimeStoreContextMut<'_>,
985    anyref: Option<&wasmtime_anyref_t>,
986    out: &mut MaybeUninit<wasmtime_structref_t>,
987) -> bool {
988    if let Some(anyref) = anyref.and_then(|a| a.as_wasmtime()) {
989        let mut scope = RootScope::new(&mut cx);
990        let rooted = anyref.to_rooted(&mut scope);
991        if let Ok(Some(structref)) = rooted.as_struct(&scope) {
992            let owned = structref.to_owned_rooted(&mut scope).expect("in scope");
993            crate::initialize(out, Some(owned).into());
994            return true;
995        }
996    }
997    crate::initialize(out, None::<OwnedRooted<StructRef>>.into());
998    false
999}
1000
1001#[unsafe(no_mangle)]
1002pub unsafe extern "C" fn wasmtime_anyref_is_array(
1003    cx: WasmtimeStoreContextMut<'_>,
1004    anyref: Option<&wasmtime_anyref_t>,
1005) -> bool {
1006    match anyref.and_then(|a| a.as_wasmtime()) {
1007        Some(anyref) => anyref.is_array(&cx).expect("OwnedRooted always in scope"),
1008        None => false,
1009    }
1010}
1011
1012#[unsafe(no_mangle)]
1013pub unsafe extern "C" fn wasmtime_anyref_as_array(
1014    mut cx: WasmtimeStoreContextMut<'_>,
1015    anyref: Option<&wasmtime_anyref_t>,
1016    out: &mut MaybeUninit<wasmtime_arrayref_t>,
1017) -> bool {
1018    if let Some(anyref) = anyref.and_then(|a| a.as_wasmtime()) {
1019        let mut scope = RootScope::new(&mut cx);
1020        let rooted = anyref.to_rooted(&mut scope);
1021        if let Ok(Some(arrayref)) = rooted.as_array(&scope) {
1022            let owned = arrayref.to_owned_rooted(&mut scope).expect("in scope");
1023            crate::initialize(out, Some(owned).into());
1024            return true;
1025        }
1026    }
1027    crate::initialize(out, None::<OwnedRooted<ArrayRef>>.into());
1028    false
1029}