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::{Service, ServiceFactory};
11
12pub struct MapErr<S, Req, F, E> {
16 service: S,
17 mapper: F,
18 _t: PhantomData<fn(Req) -> E>,
19}
20
21impl<S, Req, F, E> MapErr<S, Req, F, E> {
22 pub(crate) fn new(service: S, mapper: F) -> Self
24 where
25 S: Service<Req>,
26 F: Fn(S::Error) -> E,
27 {
28 Self {
29 service,
30 mapper,
31 _t: PhantomData,
32 }
33 }
34}
35
36impl<S, Req, F, E> Clone for MapErr<S, Req, F, E>
37where
38 S: Clone,
39 F: Clone,
40{
41 fn clone(&self) -> Self {
42 MapErr {
43 service: self.service.clone(),
44 mapper: self.mapper.clone(),
45 _t: PhantomData,
46 }
47 }
48}
49
50impl<A, Req, F, E> Service<Req> for MapErr<A, Req, F, E>
51where
52 A: Service<Req>,
53 F: Fn(A::Error) -> E + Clone,
54{
55 type Response = A::Response;
56 type Error = E;
57 type Future = MapErrFuture<A, Req, F, E>;
58
59 fn poll_ready(&self, ctx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
60 self.service.poll_ready(ctx).map_err(&self.mapper)
61 }
62
63 fn call(&self, req: Req) -> Self::Future {
64 MapErrFuture::new(self.service.call(req), self.mapper.clone())
65 }
66}
67
68pin_project! {
69 pub struct MapErrFuture<A, Req, F, E>
70 where
71 A: Service<Req>,
72 F: Fn(A::Error) -> E,
73 {
74 f: F,
75 #[pin]
76 fut: A::Future,
77 }
78}
79
80impl<A, Req, F, E> MapErrFuture<A, Req, F, E>
81where
82 A: Service<Req>,
83 F: Fn(A::Error) -> E,
84{
85 fn new(fut: A::Future, f: F) -> Self {
86 MapErrFuture { f, fut }
87 }
88}
89
90impl<A, Req, F, E> Future for MapErrFuture<A, Req, F, E>
91where
92 A: Service<Req>,
93 F: Fn(A::Error) -> E,
94{
95 type Output = Result<A::Response, E>;
96
97 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
98 let this = self.project();
99 this.fut.poll(cx).map_err(this.f)
100 }
101}
102
103pub struct MapErrServiceFactory<SF, Req, F, E>
108where
109 SF: ServiceFactory<Req>,
110 F: Fn(SF::Error) -> E + Clone,
111{
112 a: SF,
113 f: F,
114 e: PhantomData<fn(Req) -> E>,
115}
116
117impl<SF, Req, F, E> MapErrServiceFactory<SF, Req, F, E>
118where
119 SF: ServiceFactory<Req>,
120 F: Fn(SF::Error) -> E + Clone,
121{
122 pub(crate) fn new(a: SF, f: F) -> Self {
124 Self {
125 a,
126 f,
127 e: PhantomData,
128 }
129 }
130}
131
132impl<SF, Req, F, E> Clone for MapErrServiceFactory<SF, Req, F, E>
133where
134 SF: ServiceFactory<Req> + Clone,
135 F: Fn(SF::Error) -> E + Clone,
136{
137 fn clone(&self) -> Self {
138 Self {
139 a: self.a.clone(),
140 f: self.f.clone(),
141 e: PhantomData,
142 }
143 }
144}
145
146impl<SF, Req, F, E> ServiceFactory<Req> for MapErrServiceFactory<SF, Req, F, E>
147where
148 SF: ServiceFactory<Req>,
149 F: Fn(SF::Error) -> E + Clone,
150{
151 type Response = SF::Response;
152 type Error = E;
153
154 type Config = SF::Config;
155 type Service = MapErr<SF::Service, Req, F, E>;
156 type InitError = SF::InitError;
157 type Future = MapErrServiceFuture<SF, Req, F, E>;
158
159 fn new_service(&self, cfg: SF::Config) -> Self::Future {
160 MapErrServiceFuture::new(self.a.new_service(cfg), self.f.clone())
161 }
162}
163
164pin_project! {
165 pub struct MapErrServiceFuture<SF, Req, F, E>
166 where
167 SF: ServiceFactory<Req>,
168 F: Fn(SF::Error) -> E,
169 {
170 #[pin]
171 fut: SF::Future,
172 mapper: F,
173 }
174}
175
176impl<SF, Req, F, E> MapErrServiceFuture<SF, Req, F, E>
177where
178 SF: ServiceFactory<Req>,
179 F: Fn(SF::Error) -> E,
180{
181 fn new(fut: SF::Future, mapper: F) -> Self {
182 MapErrServiceFuture { fut, mapper }
183 }
184}
185
186impl<SF, Req, F, E> Future for MapErrServiceFuture<SF, Req, F, E>
187where
188 SF: ServiceFactory<Req>,
189 F: Fn(SF::Error) -> E + Clone,
190{
191 type Output = Result<MapErr<SF::Service, Req, F, E>, SF::InitError>;
192
193 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
194 let this = self.project();
195 if let Poll::Ready(svc) = this.fut.poll(cx)? {
196 Poll::Ready(Ok(MapErr::new(svc, this.mapper.clone())))
197 } else {
198 Poll::Pending
199 }
200 }
201}
202
203#[cfg(test)]
204mod tests {
205 use futures_util::future::lazy;
206
207 use super::*;
208 use crate::{err, ok, IntoServiceFactory, Ready, ServiceExt, ServiceFactoryExt};
209
210 struct Srv;
211
212 impl Service<()> for Srv {
213 type Response = ();
214 type Error = ();
215 type Future = Ready<Result<(), ()>>;
216
217 fn poll_ready(&self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
218 Poll::Ready(Err(()))
219 }
220
221 fn call(&self, _: ()) -> Self::Future {
222 err(())
223 }
224 }
225
226 #[actix_rt::test]
227 async fn test_poll_ready() {
228 let srv = Srv.map_err(|_| "error");
229 let res = lazy(|cx| srv.poll_ready(cx)).await;
230 assert_eq!(res, Poll::Ready(Err("error")));
231 }
232
233 #[actix_rt::test]
234 async fn test_call() {
235 let srv = Srv.map_err(|_| "error");
236 let res = srv.call(()).await;
237 assert!(res.is_err());
238 assert_eq!(res.err().unwrap(), "error");
239 }
240
241 #[actix_rt::test]
242 async fn test_new_service() {
243 let new_srv = (|| ok::<_, ()>(Srv)).into_factory().map_err(|_| "error");
244 let srv = new_srv.new_service(&()).await.unwrap();
245 let res = srv.call(()).await;
246 assert!(res.is_err());
247 assert_eq!(res.err().unwrap(), "error");
248 }
249}