use futures01_crate::{Async, Future};
use std::error;
use std::marker::PhantomData;
use {ErrorCompat, IntoError};
pub trait FutureExt: Future + Sized {
fn context<C, E>(self, context: C) -> Context<Self, C, E>
where
C: IntoError<E, Source = Self::Error>,
E: error::Error + ErrorCompat;
fn with_context<F, C, E>(self, context: F) -> WithContext<Self, F, E>
where
F: FnOnce() -> C,
C: IntoError<E, Source = Self::Error>,
E: error::Error + ErrorCompat;
}
impl<Fut> FutureExt for Fut
where
Fut: Future,
{
fn context<C, E>(self, context: C) -> Context<Self, C, E>
where
C: IntoError<E, Source = Self::Error>,
E: error::Error + ErrorCompat,
{
Context {
future: self,
context: Some(context),
_e: PhantomData,
}
}
fn with_context<F, C, E>(self, context: F) -> WithContext<Self, F, E>
where
F: FnOnce() -> C,
C: IntoError<E, Source = Self::Error>,
E: error::Error + ErrorCompat,
{
WithContext {
future: self,
context: Some(context),
_e: PhantomData,
}
}
}
pub struct Context<Fut, C, E> {
future: Fut,
context: Option<C>,
_e: PhantomData<E>,
}
impl<Fut, C, E> Future for Context<Fut, C, E>
where
Fut: Future,
C: IntoError<E, Source = Fut::Error>,
E: error::Error + ErrorCompat,
{
type Item = Fut::Item;
type Error = E;
fn poll(&mut self) -> Result<Async<Self::Item>, Self::Error> {
self.future.poll().map_err(|error| {
self.context
.take()
.expect("cannot poll Context after it has resolved")
.into_error(error)
})
}
}
pub struct WithContext<Fut, F, E> {
future: Fut,
context: Option<F>,
_e: PhantomData<E>,
}
impl<Fut, F, C, E> Future for WithContext<Fut, F, E>
where
Fut: Future,
F: FnOnce() -> C,
C: IntoError<E, Source = Fut::Error>,
E: error::Error + ErrorCompat,
{
type Item = Fut::Item;
type Error = E;
fn poll(&mut self) -> Result<Async<Self::Item>, Self::Error> {
self.future.poll().map_err(|error| {
let context = self
.context
.take()
.expect("cannot poll WithContext after it has resolved");
context().into_error(error)
})
}
}