Skip to main content

wasmtime_c_api/
exnref.rs

1use crate::{
2    WasmtimeStoreContextMut, handle_result, wasm_trap_t, wasmtime_error_t, wasmtime_val_t,
3};
4use std::mem::MaybeUninit;
5use wasmtime::{AsContextMut, ExnRef, ExnRefPre, ExnType, RootScope, Tag};
6
7crate::anyref::ref_wrapper!({
8    wasmtime: ExnRef,
9    capi: wasmtime_exnref_t,
10    clone: wasmtime_exnref_clone,
11    unroot: wasmtime_exnref_unroot,
12    to_raw: wasmtime_exnref_to_raw,
13    from_raw: wasmtime_exnref_from_raw,
14});
15
16#[unsafe(no_mangle)]
17pub unsafe extern "C" fn wasmtime_exnref_new(
18    mut store: WasmtimeStoreContextMut<'_>,
19    tag: &Tag,
20    fields: *const wasmtime_val_t,
21    nfields: usize,
22    exn_ret: &mut MaybeUninit<wasmtime_exnref_t>,
23) -> Option<Box<wasmtime_error_t>> {
24    let mut scope = RootScope::new(&mut store);
25
26    let result = (|| {
27        let tag_ty = tag.ty(&scope);
28        let exn_type = ExnType::from_tag_type(&tag_ty)?;
29        let allocator = ExnRefPre::new(&mut scope, exn_type);
30        let raw_fields = crate::slice_from_raw_parts(fields, nfields);
31        let field_vals: Vec<wasmtime::Val> =
32            raw_fields.iter().map(|f| f.to_val(&mut scope)).collect();
33        ExnRef::new(&mut scope, &allocator, tag, &field_vals)
34    })();
35
36    handle_result(result, |rooted| {
37        let owned = rooted.to_owned_rooted(&mut scope).unwrap();
38        exn_ret.write(owned.into());
39    })
40}
41
42#[unsafe(no_mangle)]
43pub extern "C" fn wasmtime_exnref_tag(
44    mut store: WasmtimeStoreContextMut<'_>,
45    exn: &wasmtime_exnref_t,
46    tag_ret: &mut Tag,
47) -> Option<Box<wasmtime_error_t>> {
48    let mut scope = RootScope::new(&mut store);
49    let rooted = unsafe { exn.as_wasmtime()?.to_rooted(&mut scope) };
50    handle_result(rooted.tag(&mut scope), |tag| {
51        *tag_ret = tag;
52    })
53}
54
55#[unsafe(no_mangle)]
56pub extern "C" fn wasmtime_exnref_field_count(
57    mut store: WasmtimeStoreContextMut<'_>,
58    exn: &wasmtime_exnref_t,
59) -> usize {
60    let mut scope = RootScope::new(&mut store);
61    let rooted = match unsafe { exn.as_wasmtime() } {
62        Some(e) => e.to_rooted(&mut scope),
63        None => return 0,
64    };
65    let ty = rooted.ty(&scope).unwrap();
66    ty.fields().len()
67}
68
69#[unsafe(no_mangle)]
70pub unsafe extern "C" fn wasmtime_exnref_field(
71    mut store: WasmtimeStoreContextMut<'_>,
72    exn: &wasmtime_exnref_t,
73    index: usize,
74    val_ret: &mut MaybeUninit<wasmtime_val_t>,
75) -> Option<Box<wasmtime_error_t>> {
76    let mut scope = RootScope::new(&mut store);
77    let rooted = exn.as_wasmtime()?.to_rooted(&mut scope);
78    handle_result(rooted.field(&mut scope, index), |val| {
79        crate::initialize(val_ret, wasmtime_val_t::from_val(&mut scope, val));
80    })
81}
82
83#[unsafe(no_mangle)]
84pub unsafe extern "C" fn wasmtime_context_set_exception(
85    mut store: WasmtimeStoreContextMut<'_>,
86    exn: &wasmtime_exnref_t,
87) -> Option<Box<wasm_trap_t>> {
88    let mut scope = RootScope::new(&mut store);
89    let rooted = exn.as_wasmtime()?.to_rooted(&mut scope);
90    let Err(thrown) = scope
91        .as_context_mut()
92        .throw::<std::convert::Infallible>(rooted);
93    Some(Box::new(wasm_trap_t::new(wasmtime::Error::new(thrown))))
94}
95
96#[unsafe(no_mangle)]
97pub extern "C" fn wasmtime_context_take_exception(
98    mut store: WasmtimeStoreContextMut<'_>,
99    out: &mut MaybeUninit<wasmtime_exnref_t>,
100) -> bool {
101    match store.take_pending_exception() {
102        Some(rooted) => {
103            let owned = rooted.to_owned_rooted(&mut store).unwrap();
104            out.write(owned.into());
105            true
106        }
107        None => false,
108    }
109}
110
111#[unsafe(no_mangle)]
112pub extern "C" fn wasmtime_context_has_exception(store: WasmtimeStoreContextMut<'_>) -> bool {
113    store.has_pending_exception()
114}