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