1 | use core::any::Any; |
2 | use core::pin::Pin; |
3 | use std::boxed::Box; |
4 | use std::panic::{catch_unwind, AssertUnwindSafe, UnwindSafe}; |
5 | |
6 | use futures_core::future::Future; |
7 | use futures_core::task::{Context, Poll}; |
8 | use pin_project_lite::pin_project; |
9 | |
10 | pin_project! { |
11 | /// Future for the [`catch_unwind`](super::FutureExt::catch_unwind) method. |
12 | #[derive (Debug)] |
13 | #[must_use = "futures do nothing unless you `.await` or poll them" ] |
14 | pub struct CatchUnwind<Fut> { |
15 | #[pin] |
16 | future: Fut, |
17 | } |
18 | } |
19 | |
20 | impl<Fut> CatchUnwind<Fut> |
21 | where |
22 | Fut: Future + UnwindSafe, |
23 | { |
24 | pub(super) fn new(future: Fut) -> Self { |
25 | Self { future } |
26 | } |
27 | } |
28 | |
29 | impl<Fut> Future for CatchUnwind<Fut> |
30 | where |
31 | Fut: Future + UnwindSafe, |
32 | { |
33 | type Output = Result<Fut::Output, Box<dyn Any + Send>>; |
34 | |
35 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { |
36 | let f: Pin<&mut Fut> = self.project().future; |
37 | catch_unwind(AssertUnwindSafe(|| f.poll(cx)))?.map(Ok) |
38 | } |
39 | } |
40 | |