hermit-wasm 0.1.1

Running WASM modules inside a lightweight virtual machine
Documentation
use std::error::Error;
use std::{fmt, 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> {}