use {CANCELLED_TWICE, POLLED_TWICE};
use future::{Async, EnvFuture, Poll};
use futures::Future;
pub trait EnvFutureExt<E: ?Sized>: EnvFuture<E> {
fn flatten_future(self) -> FlattenedEnvFuture<Self, Self::Item>
where Self::Item: Future,
<Self::Item as Future>::Error: From<Self::Error>,
Self: Sized,
{
FlattenedEnvFuture::EnvFuture(self)
}
}
impl<E: ?Sized, T> EnvFutureExt<E> for T where T: EnvFuture<E> {}
#[must_use = "futures do nothing unless polled"]
#[derive(Debug)]
pub enum FlattenedEnvFuture<E, F> {
EnvFuture(E),
Future(F),
Gone,
}
impl<E, F> FlattenedEnvFuture<E, F> {
pub fn take_future(&mut self) -> F {
use std::mem;
match mem::replace(self, FlattenedEnvFuture::Gone) {
FlattenedEnvFuture::Future(f) => f,
_ => panic!("can only unwrap `Future` variant"),
}
}
}
impl<E: ?Sized, EF, F> EnvFuture<E> for FlattenedEnvFuture<EF, F>
where EF: EnvFuture<E, Item = F>,
F: Future,
F::Error: From<EF::Error>,
{
type Item = F::Item;
type Error = F::Error;
fn poll(&mut self, env: &mut E) -> Poll<Self::Item, Self::Error> {
let mut f = match *self {
FlattenedEnvFuture::EnvFuture(ref mut e) => try_ready!(e.poll(env)),
FlattenedEnvFuture::Future(ref mut f) => return Ok(Async::Ready(try_ready!(f.poll()))),
FlattenedEnvFuture::Gone => panic!(POLLED_TWICE),
};
let ret = f.poll();
*self = FlattenedEnvFuture::Future(f);
Ok(Async::Ready(try_ready!(ret)))
}
fn cancel(&mut self, env: &mut E) {
match *self {
FlattenedEnvFuture::EnvFuture(ref mut e) => e.cancel(env),
FlattenedEnvFuture::Future(_) => {},
FlattenedEnvFuture::Gone => panic!(CANCELLED_TWICE),
}
*self = FlattenedEnvFuture::Gone;
}
}