futures_util/future/
catch_unwind.rs1use std::prelude::v1::*;
2use std::any::Any;
3use std::panic::{catch_unwind, UnwindSafe, AssertUnwindSafe};
4
5use futures_core::{Future, Poll, Async};
6use futures_core::task;
7
8#[derive(Debug)]
12#[must_use = "futures do nothing unless polled"]
13pub struct CatchUnwind<F> where F: Future {
14 future: Option<F>,
15}
16
17pub fn new<F>(future: F) -> CatchUnwind<F>
18 where F: Future + UnwindSafe,
19{
20 CatchUnwind {
21 future: Some(future),
22 }
23}
24
25impl<F> Future for CatchUnwind<F>
26 where F: Future + UnwindSafe,
27{
28 type Item = Result<F::Item, F::Error>;
29 type Error = Box<Any + Send>;
30
31 fn poll(&mut self, cx: &mut task::Context) -> Poll<Self::Item, Self::Error> {
32 let mut future = self.future.take().expect("cannot poll twice");
33 let (res, future) = catch_unwind(AssertUnwindSafe(|| {
34 (future.poll(cx), future)
35 }))?;
36 match res {
37 Ok(Async::Pending) => {
38 self.future = Some(future);
39 Ok(Async::Pending)
40 }
41 Ok(Async::Ready(t)) => Ok(Async::Ready(Ok(t))),
42 Err(e) => Ok(Async::Ready(Err(e))),
43 }
44 }
45}