1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
use std::error::Error;
use std::fmt;
use std::marker;
/// An error returned from the `proc_exit` host syscall.
///
/// Embedders can test if an error returned from wasm is this error, in which
/// case it may signal a non-fatal trap.
#[derive(Debug)]
pub struct I32Exit(pub i32);
impl I32Exit {
/// Accessor for an exit code appropriate for calling `std::process::exit` with,
/// when interpreting this `I32Exit` as an exit for the parent process.
///
/// This method masks off exit codes which are illegal on Windows.
pub fn process_exit_code(&self) -> i32 {
if cfg!(windows) && self.0 >= 3 {
1
} else {
self.0
}
}
}
impl fmt::Display for I32Exit {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Exited with i32 exit status {}", self.0)
}
}
impl std::error::Error for I32Exit {}
/// A helper error type used by many other modules through type aliases.
///
/// This type is an `Error` itself and is intended to be a representation of
/// either:
///
/// * A custom error type `T`
/// * A trap, represented as `anyhow::Error`
///
/// This error is created through either the `::trap` constructor representing a
/// full-fledged trap or the `From<T>` constructor which is intended to be used
/// with `?`. The goal is to make normal errors `T` "automatic" but enable error
/// paths to return a `::trap` error optionally still as necessary without extra
/// boilerplate everywhere else.
///
/// Note that this type isn't used directly but instead is intended to be used
/// as:
///
/// ```rust,ignore
/// type MyError = TrappableError<bindgen::TheError>;
/// ```
///
/// where `MyError` is what you'll use throughout bindings code and
/// `bindgen::TheError` is the type that this represents as generated by the
/// `bindgen!` macro.
#[repr(transparent)]
pub struct TrappableError<T> {
err: anyhow::Error,
_marker: marker::PhantomData<T>,
}
impl<T> TrappableError<T> {
pub fn trap(err: impl Into<anyhow::Error>) -> TrappableError<T> {
TrappableError {
err: err.into(),
_marker: marker::PhantomData,
}
}
pub fn downcast(self) -> anyhow::Result<T>
where
T: Error + Send + Sync + 'static,
{
self.err.downcast()
}
pub fn downcast_ref(&self) -> Option<&T>
where
T: Error + Send + Sync + 'static,
{
self.err.downcast_ref()
}
}
impl<T> From<T> for TrappableError<T>
where
T: Error + Send + Sync + 'static,
{
fn from(error: T) -> Self {
Self {
err: error.into(),
_marker: marker::PhantomData,
}
}
}
impl<T> fmt::Debug for TrappableError<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.err.fmt(f)
}
}
impl<T> fmt::Display for TrappableError<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.err.fmt(f)
}
}
impl<T> Error for TrappableError<T> {}