Skip to content

Commit

Permalink
refactor Trap type
Browse files Browse the repository at this point in the history
- Trap no longer is Clone
- Added Trap::{downcast_mut, downcast} methods
  • Loading branch information
Robbepop committed Feb 4, 2023
1 parent 323c0cf commit f4368bd
Showing 1 changed file with 49 additions and 4 deletions.
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

0 comments on commit f4368bd

Please sign in to comment.