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