actix 0.10.0

Actor framework for Rust
Documentation
use pin_project::pin_project;
use std::pin::Pin;
use std::task::{Context, Poll};

use crate::actor::Actor;
use crate::fut::ActorFuture;

#[pin_project(project = ChainProj)]
#[must_use = "futures do nothing unless you `.await` or poll them"]
#[derive(Debug)]
pub enum Chain<A, B, C> {
    First(#[pin] A, Option<C>),
    Second(#[pin] B),
    Empty,
}

impl<A, B, C> Chain<A, B, C>
where
    A: ActorFuture,
    B: ActorFuture<Actor = A::Actor>,
{
    pub fn new(fut1: A, data: C) -> Chain<A, B, C> {
        Chain::First(fut1, Some(data))
    }

    pub fn poll<F>(
        mut self: Pin<&mut Self>,
        srv: &mut A::Actor,
        ctx: &mut <A::Actor as Actor>::Context,
        task: &mut Context<'_>,
        f: F,
    ) -> Poll<B::Output>
    where
        F: FnOnce(A::Output, C, &mut A::Actor, &mut <A::Actor as Actor>::Context) -> B,
    {
        let mut f = Some(f);

        loop {
            let this = self.as_mut().project();
            let (output, data) = match this {
                ChainProj::First(fut1, data) => {
                    let output = match fut1.poll(srv, ctx, task) {
                        Poll::Ready(t) => t,
                        Poll::Pending => return Poll::Pending,
                    };
                    (output, data.take().unwrap())
                }
                ChainProj::Second(fut2) => {
                    return fut2.poll(srv, ctx, task);
                }
                ChainProj::Empty => unreachable!(),
            };

            self.set(Chain::Empty);
            let fut2 = (f.take().unwrap())(output, data, srv, ctx);
            self.set(Chain::Second(fut2))
        }
    }
}