use std::marker::PhantomData;
use futures::{Future, Poll};
use common::{Func, Tuple};
use endpoint::{ApplyContext, ApplyResult, Endpoint};
use error::Error;
use super::Wrapper;
pub fn map<T, F>(f: F) -> Map<T, F>
where
T: Tuple,
F: Func<T>,
{
Map {
f,
_marker: PhantomData,
}
}
#[allow(missing_docs)]
#[derive(Debug)]
pub struct Map<T, F> {
f: F,
_marker: PhantomData<fn(T)>,
}
impl<'a, E, F> Wrapper<'a, E> for Map<E::Output, F>
where
E: Endpoint<'a>,
F: Func<E::Output> + 'a,
{
type Output = (F::Out,);
type Endpoint = MapEndpoint<E, F>;
fn wrap(self, endpoint: E) -> Self::Endpoint {
MapEndpoint {
endpoint,
f: self.f,
}
}
}
#[derive(Debug, Copy, Clone)]
pub struct MapEndpoint<E, F> {
endpoint: E,
f: F,
}
impl<'a, E, F> Endpoint<'a> for MapEndpoint<E, F>
where
E: Endpoint<'a>,
F: Func<E::Output> + 'a,
{
type Output = (F::Out,);
type Future = MapFuture<'a, E::Future, F>;
#[inline]
fn apply(&'a self, ecx: &mut ApplyContext<'_>) -> ApplyResult<Self::Future> {
Ok(MapFuture {
future: self.endpoint.apply(ecx)?,
f: Some(&self.f),
})
}
}
#[derive(Debug)]
pub struct MapFuture<'a, T, F: 'a> {
future: T,
f: Option<&'a F>,
}
impl<'a, T, F> Future for MapFuture<'a, T, F>
where
T: Future<Error = Error>,
T::Item: Tuple,
F: Func<T::Item> + 'a,
{
type Item = (F::Out,);
type Error = Error;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
let item = try_ready!(self.future.poll());
let f = self.f.take().expect("this future has already polled.");
Ok((f.call(item),).into())
}
}