Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor Trap type #650

Merged
merged 1 commit into from
Feb 4, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 49 additions & 4 deletions crates/core/src/trap.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::HostError;
use alloc::{boxed::Box, string::String, sync::Arc};
use alloc::{boxed::Box, string::String};
use core::fmt::{self, Display};

#[cfg(feature = "std")]
Expand All @@ -11,10 +11,10 @@ use std::error::Error as StdError;
/// which immediately aborts execution.
/// Traps cannot be handled by WebAssembly code, but are reported to the
/// host embedder.
#[derive(Debug, Clone)]
#[derive(Debug)]
pub struct Trap {
/// The cloneable reason of a [`Trap`].
reason: Arc<TrapReason>,
reason: Box<TrapReason>,
}

#[test]
Expand Down Expand Up @@ -62,6 +62,24 @@ impl TrapReason {
None
}

/// Returns an exclusive reference to the [`HostError`] if any.
#[inline]
pub fn as_host_mut(&mut self) -> Option<&mut dyn HostError> {
if let Self::Host(host_error) = self {
return Some(&mut **host_error);
}
None
}

/// Consumes `self` to return the [`HostError`] if any.
#[inline]
pub fn into_host(self) -> Option<Box<dyn HostError>> {
if let Self::Host(host_error) = self {
return Some(host_error);
}
None
}

/// Returns the [`TrapCode`] traps originating from Wasm execution.
#[inline]
pub fn trap_code(&self) -> Option<TrapCode> {
Expand All @@ -76,7 +94,7 @@ impl Trap {
/// Create a new [`Trap`] from the [`TrapReason`].
fn with_reason(reason: TrapReason) -> Self {
Self {
reason: Arc::new(reason),
reason: Box::new(reason),
}
}

Expand All @@ -102,6 +120,33 @@ impl Trap {
.and_then(<(dyn HostError + 'static)>::downcast_ref)
}

/// Downcasts the [`Trap`] into the `T: HostError` if possible.
///
/// Returns `None` otherwise.
#[inline]
pub fn downcast_mut<T>(&mut self) -> Option<&mut T>
where
T: HostError,
{
self.reason
.as_host_mut()
.and_then(<(dyn HostError + 'static)>::downcast_mut)
}

/// Consumes `self` to downcast the [`Trap`] into the `T: HostError` if possible.
///
/// Returns `None` otherwise.
#[inline]
pub fn downcast<T>(self) -> Option<T>
where
T: HostError,
{
self.reason
.into_host()
.and_then(|error| error.downcast().ok())
.map(|boxed| *boxed)
}

/// Creates a new `Trap` representing an explicit program exit with a classic `i32`
/// exit status value.
#[cold] // see Trap::new
Expand Down