actix/fut/future/
then.rs

1use std::{
2    pin::Pin,
3    task::{self, Poll},
4};
5
6use futures_core::ready;
7use pin_project_lite::pin_project;
8
9use crate::{actor::Actor, fut::ActorFuture};
10
11pin_project! {
12    /// Future for the [`then`](super::ActorFutureExt::then) combinator, chaining computations on the end of
13    /// another future regardless of its outcome.
14    ///
15    /// This is created by the `ActorFuture::then` method.
16    #[project = ThenProj]
17    #[derive(Debug)]
18    #[must_use = "futures do nothing unless polled"]
19    pub enum Then<A, B, F> {
20        First {
21            #[pin]
22            fut1: A,
23            data: Option<F>,
24        },
25        Second {
26            #[pin]
27            fut2: B
28        },
29        Empty,
30    }
31}
32
33pub(super) fn new<A, B, F, Act>(future: A, f: F) -> Then<A, B, F>
34where
35    A: ActorFuture<Act>,
36    B: ActorFuture<Act>,
37    Act: Actor,
38{
39    Then::First {
40        fut1: future,
41        data: Some(f),
42    }
43}
44
45impl<A, B, F, Act> ActorFuture<Act> for Then<A, B, F>
46where
47    A: ActorFuture<Act>,
48    B: ActorFuture<Act>,
49    F: FnOnce(A::Output, &mut Act, &mut Act::Context) -> B,
50    Act: Actor,
51{
52    type Output = B::Output;
53
54    fn poll(
55        mut self: Pin<&mut Self>,
56        act: &mut Act,
57        ctx: &mut Act::Context,
58        task: &mut task::Context<'_>,
59    ) -> Poll<B::Output> {
60        match self.as_mut().project() {
61            ThenProj::First { fut1, data } => {
62                let output = ready!(fut1.poll(act, ctx, task));
63                let data = data.take().unwrap();
64                let fut2 = data(output, act, ctx);
65                self.set(Then::Second { fut2 });
66                self.poll(act, ctx, task)
67            }
68            ThenProj::Second { fut2 } => {
69                let res = ready!(fut2.poll(act, ctx, task));
70                self.set(Then::Empty);
71                Poll::Ready(res)
72            }
73            ThenProj::Empty => panic!("ActorFuture polled after finish"),
74        }
75    }
76}