xref: /wasmtime-44.0.1/crates/c-api/src/exn.rs (revision 0dbb6f3d)
1 use crate::{
2     WasmtimeStoreContextMut, handle_result, wasm_trap_t, wasmtime_error_t, wasmtime_val_t,
3 };
4 use std::mem::MaybeUninit;
5 use wasmtime::{AsContextMut, ExnRef, ExnRefPre, ExnType, RootScope, Tag};
6 
7 /// An opaque type representing a WebAssembly exception object.
8 pub struct wasmtime_exn_t {
9     exn: wasmtime::OwnedRooted<ExnRef>,
10 }
11 
12 wasmtime_c_api_macros::declare_own!(wasmtime_exn_t);
13 
14 #[unsafe(no_mangle)]
wasmtime_exn_new( mut store: WasmtimeStoreContextMut<'_>, tag: &Tag, fields: *const wasmtime_val_t, nfields: usize, exn_ret: &mut *mut wasmtime_exn_t, ) -> Option<Box<wasmtime_error_t>>15 pub unsafe extern "C" fn wasmtime_exn_new(
16     mut store: WasmtimeStoreContextMut<'_>,
17     tag: &Tag,
18     fields: *const wasmtime_val_t,
19     nfields: usize,
20     exn_ret: &mut *mut wasmtime_exn_t,
21 ) -> Option<Box<wasmtime_error_t>> {
22     let mut scope = RootScope::new(&mut store);
23 
24     let result = (|| {
25         let tag_ty = tag.ty(&scope);
26         let exn_type = ExnType::from_tag_type(&tag_ty)?;
27         let allocator = ExnRefPre::new(&mut scope, exn_type);
28         let raw_fields = crate::slice_from_raw_parts(fields, nfields);
29         let field_vals: Vec<wasmtime::Val> =
30             raw_fields.iter().map(|f| f.to_val(&mut scope)).collect();
31         ExnRef::new(&mut scope, &allocator, tag, &field_vals)
32     })();
33 
34     handle_result(result, |rooted| {
35         let owned = rooted.to_owned_rooted(&mut scope).unwrap();
36         *exn_ret = Box::into_raw(Box::new(wasmtime_exn_t { exn: owned }));
37     })
38 }
39 
40 #[unsafe(no_mangle)]
wasmtime_exn_tag( mut store: WasmtimeStoreContextMut<'_>, exn: &wasmtime_exn_t, tag_ret: &mut Tag, ) -> Option<Box<wasmtime_error_t>>41 pub extern "C" fn wasmtime_exn_tag(
42     mut store: WasmtimeStoreContextMut<'_>,
43     exn: &wasmtime_exn_t,
44     tag_ret: &mut Tag,
45 ) -> Option<Box<wasmtime_error_t>> {
46     let mut scope = RootScope::new(&mut store);
47     let rooted = exn.exn.to_rooted(&mut scope);
48     handle_result(rooted.tag(&mut scope), |tag| {
49         *tag_ret = tag;
50     })
51 }
52 
53 #[unsafe(no_mangle)]
wasmtime_exn_field_count( mut store: WasmtimeStoreContextMut<'_>, exn: &wasmtime_exn_t, ) -> usize54 pub extern "C" fn wasmtime_exn_field_count(
55     mut store: WasmtimeStoreContextMut<'_>,
56     exn: &wasmtime_exn_t,
57 ) -> usize {
58     let mut scope = RootScope::new(&mut store);
59     let rooted = exn.exn.to_rooted(&mut scope);
60     let ty = rooted.ty(&scope).unwrap();
61     ty.fields().len()
62 }
63 
64 #[unsafe(no_mangle)]
wasmtime_exn_field( mut store: WasmtimeStoreContextMut<'_>, exn: &wasmtime_exn_t, index: usize, val_ret: &mut MaybeUninit<wasmtime_val_t>, ) -> Option<Box<wasmtime_error_t>>65 pub unsafe extern "C" fn wasmtime_exn_field(
66     mut store: WasmtimeStoreContextMut<'_>,
67     exn: &wasmtime_exn_t,
68     index: usize,
69     val_ret: &mut MaybeUninit<wasmtime_val_t>,
70 ) -> Option<Box<wasmtime_error_t>> {
71     let mut scope = RootScope::new(&mut store);
72     let rooted = exn.exn.to_rooted(&mut scope);
73     handle_result(rooted.field(&mut scope, index), |val| {
74         crate::initialize(val_ret, wasmtime_val_t::from_val(&mut scope, val));
75     })
76 }
77 
78 #[unsafe(no_mangle)]
wasmtime_context_set_exception( mut store: WasmtimeStoreContextMut<'_>, exn: Box<wasmtime_exn_t>, ) -> Box<wasm_trap_t>79 pub unsafe extern "C" fn wasmtime_context_set_exception(
80     mut store: WasmtimeStoreContextMut<'_>,
81     exn: Box<wasmtime_exn_t>,
82 ) -> Box<wasm_trap_t> {
83     let mut scope = RootScope::new(&mut store);
84     let rooted = exn.exn.to_rooted(&mut scope);
85     let thrown = scope.as_context_mut().throw::<()>(rooted).unwrap_err();
86     Box::new(wasm_trap_t::new(wasmtime::Error::new(thrown)))
87 }
88 
89 #[unsafe(no_mangle)]
wasmtime_context_take_exception( mut store: WasmtimeStoreContextMut<'_>, exn_ret: &mut *mut wasmtime_exn_t, ) -> bool90 pub extern "C" fn wasmtime_context_take_exception(
91     mut store: WasmtimeStoreContextMut<'_>,
92     exn_ret: &mut *mut wasmtime_exn_t,
93 ) -> bool {
94     match store.take_pending_exception() {
95         Some(rooted) => {
96             let owned = rooted.to_owned_rooted(&mut store).unwrap();
97             *exn_ret = Box::into_raw(Box::new(wasmtime_exn_t { exn: owned }));
98             true
99         }
100         None => false,
101     }
102 }
103 
104 #[unsafe(no_mangle)]
wasmtime_context_has_exception(store: WasmtimeStoreContextMut<'_>) -> bool105 pub extern "C" fn wasmtime_context_has_exception(store: WasmtimeStoreContextMut<'_>) -> bool {
106     store.has_pending_exception()
107 }
108