1 use crate::{wasm_frame_vec_t, wasm_name_t}; 2 use anyhow::{Error, Result, anyhow}; 3 4 #[repr(C)] 5 pub struct wasmtime_error_t { 6 error: Error, 7 } 8 9 wasmtime_c_api_macros::declare_own!(wasmtime_error_t); 10 11 impl From<Error> for wasmtime_error_t { 12 fn from(error: Error) -> wasmtime_error_t { 13 wasmtime_error_t { error } 14 } 15 } 16 17 impl From<wasmtime_error_t> for Error { 18 fn from(cerr: wasmtime_error_t) -> Error { 19 cerr.error 20 } 21 } 22 23 #[unsafe(no_mangle)] 24 pub extern "C" fn wasmtime_error_new( 25 msg: *const std::ffi::c_char, 26 ) -> Option<Box<wasmtime_error_t>> { 27 let msg_bytes = unsafe { std::ffi::CStr::from_ptr(msg).to_bytes() }; 28 let msg_string = String::from_utf8_lossy(msg_bytes).into_owned(); 29 Some(Box::new(wasmtime_error_t::from(anyhow!(msg_string)))) 30 } 31 32 pub(crate) fn handle_result<T>( 33 result: Result<T>, 34 ok: impl FnOnce(T), 35 ) -> Option<Box<wasmtime_error_t>> { 36 match result { 37 Ok(value) => { 38 ok(value); 39 None 40 } 41 Err(error) => Some(Box::new(wasmtime_error_t { error })), 42 } 43 } 44 45 pub(crate) fn bad_utf8() -> Option<Box<wasmtime_error_t>> { 46 Some(Box::new(wasmtime_error_t { 47 error: anyhow!("input was not valid utf-8"), 48 })) 49 } 50 51 #[unsafe(no_mangle)] 52 pub extern "C" fn wasmtime_error_message(error: &wasmtime_error_t, message: &mut wasm_name_t) { 53 message.set_buffer(format!("{:?}", error.error).into_bytes()); 54 } 55 56 #[unsafe(no_mangle)] 57 pub extern "C" fn wasmtime_error_exit_status(raw: &wasmtime_error_t, status: &mut i32) -> bool { 58 #[cfg(feature = "wasi")] 59 if let Some(exit) = raw.error.downcast_ref::<wasmtime_wasi::I32Exit>() { 60 *status = exit.0; 61 return true; 62 } 63 64 // Squash unused warnings in wasi-disabled builds. 65 drop((raw, status)); 66 67 false 68 } 69 70 #[unsafe(no_mangle)] 71 pub extern "C" fn wasmtime_error_wasm_trace<'a>( 72 raw: &'a wasmtime_error_t, 73 out: &mut wasm_frame_vec_t<'a>, 74 ) { 75 crate::trap::error_trace(&raw.error, out) 76 } 77