actix_service/
transform_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::Transform;
11
12/// Transform for the [`TransformExt::map_init_err`] combinator, changing the type of a new
13/// [`Transform`]'s initialization error.
14pub struct TransformMapInitErr<T, S, Req, F, E> {
15    transform: T,
16    mapper: F,
17    _phantom: PhantomData<fn(Req) -> (S, E)>,
18}
19
20impl<T, S, F, E, Req> TransformMapInitErr<T, S, Req, F, E> {
21    pub(crate) fn new(t: T, f: F) -> Self
22    where
23        T: Transform<S, Req>,
24        F: Fn(T::InitError) -> E,
25    {
26        Self {
27            transform: t,
28            mapper: f,
29            _phantom: PhantomData,
30        }
31    }
32}
33
34impl<T, S, Req, F, E> Clone for TransformMapInitErr<T, S, Req, F, E>
35where
36    T: Clone,
37    F: Clone,
38{
39    fn clone(&self) -> Self {
40        Self {
41            transform: self.transform.clone(),
42            mapper: self.mapper.clone(),
43            _phantom: PhantomData,
44        }
45    }
46}
47
48impl<T, S, F, E, Req> Transform<S, Req> for TransformMapInitErr<T, S, Req, F, E>
49where
50    T: Transform<S, Req>,
51    F: Fn(T::InitError) -> E + Clone,
52{
53    type Response = T::Response;
54    type Error = T::Error;
55    type Transform = T::Transform;
56
57    type InitError = E;
58    type Future = TransformMapInitErrFuture<T, S, F, E, Req>;
59
60    fn new_transform(&self, service: S) -> Self::Future {
61        TransformMapInitErrFuture {
62            fut: self.transform.new_transform(service),
63            f: self.mapper.clone(),
64        }
65    }
66}
67
68pin_project! {
69    pub struct TransformMapInitErrFuture<T, S, F, E, Req>
70    where
71    T: Transform<S, Req>,
72    F: Fn(T::InitError) -> E,
73    {
74        #[pin]
75        fut: T::Future,
76        f: F,
77    }
78}
79
80impl<T, S, F, E, Req> Future for TransformMapInitErrFuture<T, S, F, E, Req>
81where
82    T: Transform<S, Req>,
83    F: Fn(T::InitError) -> E + Clone,
84{
85    type Output = Result<T::Transform, E>;
86
87    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
88        let this = self.project();
89        if let Poll::Ready(res) = this.fut.poll(cx) {
90            Poll::Ready(res.map_err(this.f))
91        } else {
92            Poll::Pending
93        }
94    }
95}