futures_util/future/
catch_unwind.rs

1use 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/// Future for the `catch_unwind` combinator.
9///
10/// This is created by the `Future::catch_unwind` method.
11#[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}