use crate::worker::TaskExecError; use futures::future::BoxFuture; use futures::FutureExt; use std::future::Future; use std::pin::Pin; use std::task::Context; use std::task::Poll; pub(crate) struct CatchUnwindFuture { inner: BoxFuture<'static, F::Output>, } impl CatchUnwindFuture { pub fn create(f: F) -> CatchUnwindFuture { Self { inner: f.boxed() } } } impl Future for CatchUnwindFuture { type Output = Result; fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let inner = &mut self.inner; match catch_unwind(move || inner.poll_unpin(cx)) { Ok(Poll::Pending) => Poll::Pending, Ok(Poll::Ready(value)) => Poll::Ready(Ok(value)), Err(cause) => Poll::Ready(Err(cause)), } } } fn catch_unwind R, R>(f: F) -> Result { match std::panic::catch_unwind(std::panic::AssertUnwindSafe(f)) { Ok(res) => Ok(res), Err(cause) => match cause.downcast_ref::<&'static str>() { None => match cause.downcast_ref::() { None => Err(TaskExecError::Panicked( "Sorry, unknown panic message".to_string(), )), Some(message) => Err(TaskExecError::Panicked(message.to_string())), }, Some(message) => Err(TaskExecError::Panicked(message.to_string())), }, } }