actix/fut/future/
map.rs

1use std::{
2    pin::Pin,
3    task::{Context, 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 [`map`](super::ActorFutureExt::map) method.
13    #[project = MapProj]
14    #[project_replace = MapProjReplace]
15    #[derive(Debug)]
16    #[must_use = "futures do nothing unless you `.await` or poll them"]
17    pub enum Map<Fut, F> {
18        Incomplete {
19            #[pin]
20            future: Fut,
21            f: F,
22        },
23        Complete,
24    }
25}
26
27impl<Fut, F> Map<Fut, F> {
28    pub(super) fn new(future: Fut, f: F) -> Self {
29        Self::Incomplete { future, f }
30    }
31}
32
33impl<U, Fut, A, F> ActorFuture<A> for Map<Fut, F>
34where
35    Fut: ActorFuture<A>,
36    A: Actor,
37    F: FnOnce(Fut::Output, &mut A, &mut A::Context) -> U,
38{
39    type Output = U;
40
41    fn poll(
42        mut self: Pin<&mut Self>,
43        act: &mut A,
44        ctx: &mut A::Context,
45        task: &mut Context<'_>,
46    ) -> Poll<Self::Output> {
47        match self.as_mut().project() {
48            MapProj::Incomplete { future, .. } => {
49                let output = ready!(future.poll(act, ctx, task));
50                match self.project_replace(Map::Complete) {
51                    MapProjReplace::Incomplete { f, .. } => Poll::Ready(f(output, act, ctx)),
52                    MapProjReplace::Complete => unreachable!(),
53                }
54            }
55            MapProj::Complete => {
56                panic!("Map must not be polled after it returned `Poll::Ready`")
57            }
58        }
59    }
60}