actix_service/
map_init_err.rs

1use core::{
2    future::Future,
3    marker::PhantomData,
4    pin::Pin,
5    task::{Context, Poll},
6};
7
8use pin_project_lite::pin_project;
9
10use super::ServiceFactory;
11
12/// `MapInitErr` service combinator
13pub struct MapInitErr<A, F, Req, Err> {
14    a: A,
15    f: F,
16    e: PhantomData<fn(Req) -> Err>,
17}
18
19impl<A, F, Req, Err> MapInitErr<A, F, Req, Err>
20where
21    A: ServiceFactory<Req>,
22    F: Fn(A::InitError) -> Err,
23{
24    /// Create new `MapInitErr` combinator
25    pub(crate) fn new(a: A, f: F) -> Self {
26        Self {
27            a,
28            f,
29            e: PhantomData,
30        }
31    }
32}
33
34impl<A, F, Req, E> Clone for MapInitErr<A, F, Req, E>
35where
36    A: Clone,
37    F: Clone,
38{
39    fn clone(&self) -> Self {
40        Self {
41            a: self.a.clone(),
42            f: self.f.clone(),
43            e: PhantomData,
44        }
45    }
46}
47
48impl<A, F, Req, E> ServiceFactory<Req> for MapInitErr<A, F, Req, E>
49where
50    A: ServiceFactory<Req>,
51    F: Fn(A::InitError) -> E + Clone,
52{
53    type Response = A::Response;
54    type Error = A::Error;
55
56    type Config = A::Config;
57    type Service = A::Service;
58    type InitError = E;
59    type Future = MapInitErrFuture<A, F, Req, E>;
60
61    fn new_service(&self, cfg: A::Config) -> Self::Future {
62        MapInitErrFuture::new(self.a.new_service(cfg), self.f.clone())
63    }
64}
65
66pin_project! {
67    pub struct MapInitErrFuture<A, F, Req, E>
68    where
69        A: ServiceFactory<Req>,
70        F: Fn(A::InitError) -> E,
71    {
72        f: F,
73        #[pin]
74        fut: A::Future,
75    }
76}
77
78impl<A, F, Req, E> MapInitErrFuture<A, F, Req, E>
79where
80    A: ServiceFactory<Req>,
81    F: Fn(A::InitError) -> E,
82{
83    fn new(fut: A::Future, f: F) -> Self {
84        MapInitErrFuture { f, fut }
85    }
86}
87
88impl<A, F, Req, E> Future for MapInitErrFuture<A, F, Req, E>
89where
90    A: ServiceFactory<Req>,
91    F: Fn(A::InitError) -> E,
92{
93    type Output = Result<A::Service, E>;
94
95    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
96        let this = self.project();
97        this.fut.poll(cx).map_err(this.f)
98    }
99}