use std::any::Any;
use std::panic::{catch_unwind, AssertUnwindSafe};
pub(crate) fn catch_host<R>(call: impl FnOnce() -> R) -> Result<R, Box<dyn Any + Send>> {
catch_unwind(AssertUnwindSafe(call))
}
pub(crate) fn reraise(payload: Box<dyn Any + Send>) -> ! {
std::panic::resume_unwind(payload)
}
pub(crate) fn restore_after_panic(inner: &mut crate::store::StoreInner, roots_mark: usize) {
let _ = inner.take_exec();
inner.gc_roots_truncate(roots_mark);
inner.take_pending_exception();
}
#[cfg(feature = "async")]
pub(crate) struct CatchUnwind<F>(pub(crate) F);
#[cfg(feature = "async")]
impl<F: std::future::Future + Unpin> std::future::Future for CatchUnwind<F> {
type Output = Result<F::Output, Box<dyn Any + Send>>;
fn poll(
self: std::pin::Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
) -> std::task::Poll<Self::Output> {
use std::task::Poll;
let inner = &mut self.get_mut().0;
match catch_unwind(AssertUnwindSafe(|| std::pin::Pin::new(inner).poll(cx))) {
Ok(Poll::Pending) => Poll::Pending,
Ok(Poll::Ready(v)) => Poll::Ready(Ok(v)),
Err(payload) => Poll::Ready(Err(payload)),
}
}
}