1use std::future::Future;
2use std::marker::PhantomData;
3use std::task::{Context, Poll};
4
5use futures_util::future::{ok, Ready};
6
7use crate::{IntoService, IntoServiceFactory, Service, ServiceFactory};
8
9pub fn fn_service<F, Fut, Req, Res, Err, Cfg>(
11 f: F,
12) -> FnServiceFactory<F, Fut, Req, Res, Err, Cfg>
13where
14 F: FnMut(Req) -> Fut + Clone,
15 Fut: Future<Output = Result<Res, Err>>,
16{
17 FnServiceFactory::new(f)
18}
19
20pub fn fn_factory<F, Cfg, Srv, Fut, Err>(f: F) -> FnServiceNoConfig<F, Cfg, Srv, Fut, Err>
57where
58 Srv: Service,
59 F: Fn() -> Fut,
60 Fut: Future<Output = Result<Srv, Err>>,
61{
62 FnServiceNoConfig::new(f)
63}
64
65pub fn fn_factory_with_config<F, Fut, Cfg, Srv, Err>(
96 f: F,
97) -> FnServiceConfig<F, Fut, Cfg, Srv, Err>
98where
99 F: Fn(Cfg) -> Fut,
100 Fut: Future<Output = Result<Srv, Err>>,
101 Srv: Service,
102{
103 FnServiceConfig::new(f)
104}
105
106pub struct FnService<F, Fut, Req, Res, Err>
107where
108 F: FnMut(Req) -> Fut,
109 Fut: Future<Output = Result<Res, Err>>,
110{
111 f: F,
112 _t: PhantomData<Req>,
113}
114
115impl<F, Fut, Req, Res, Err> FnService<F, Fut, Req, Res, Err>
116where
117 F: FnMut(Req) -> Fut,
118 Fut: Future<Output = Result<Res, Err>>,
119{
120 pub(crate) fn new(f: F) -> Self {
121 Self { f, _t: PhantomData }
122 }
123}
124
125impl<F, Fut, Req, Res, Err> Clone for FnService<F, Fut, Req, Res, Err>
126where
127 F: FnMut(Req) -> Fut + Clone,
128 Fut: Future<Output = Result<Res, Err>>,
129{
130 fn clone(&self) -> Self {
131 Self::new(self.f.clone())
132 }
133}
134
135impl<F, Fut, Req, Res, Err> Service for FnService<F, Fut, Req, Res, Err>
136where
137 F: FnMut(Req) -> Fut,
138 Fut: Future<Output = Result<Res, Err>>,
139{
140 type Request = Req;
141 type Response = Res;
142 type Error = Err;
143 type Future = Fut;
144
145 fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
146 Poll::Ready(Ok(()))
147 }
148
149 fn call(&mut self, req: Req) -> Self::Future {
150 (self.f)(req)
151 }
152}
153
154impl<F, Fut, Req, Res, Err> IntoService<FnService<F, Fut, Req, Res, Err>> for F
155where
156 F: FnMut(Req) -> Fut,
157 Fut: Future<Output = Result<Res, Err>>,
158{
159 fn into_service(self) -> FnService<F, Fut, Req, Res, Err> {
160 FnService::new(self)
161 }
162}
163
164pub struct FnServiceFactory<F, Fut, Req, Res, Err, Cfg>
165where
166 F: FnMut(Req) -> Fut,
167 Fut: Future<Output = Result<Res, Err>>,
168{
169 f: F,
170 _t: PhantomData<(Req, Cfg)>,
171}
172
173impl<F, Fut, Req, Res, Err, Cfg> FnServiceFactory<F, Fut, Req, Res, Err, Cfg>
174where
175 F: FnMut(Req) -> Fut + Clone,
176 Fut: Future<Output = Result<Res, Err>>,
177{
178 fn new(f: F) -> Self {
179 FnServiceFactory { f, _t: PhantomData }
180 }
181}
182
183impl<F, Fut, Req, Res, Err, Cfg> Clone for FnServiceFactory<F, Fut, Req, Res, Err, Cfg>
184where
185 F: FnMut(Req) -> Fut + Clone,
186 Fut: Future<Output = Result<Res, Err>>,
187{
188 fn clone(&self) -> Self {
189 Self::new(self.f.clone())
190 }
191}
192
193impl<F, Fut, Req, Res, Err> Service for FnServiceFactory<F, Fut, Req, Res, Err, ()>
194where
195 F: FnMut(Req) -> Fut + Clone,
196 Fut: Future<Output = Result<Res, Err>>,
197{
198 type Request = Req;
199 type Response = Res;
200 type Error = Err;
201 type Future = Fut;
202
203 fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
204 Poll::Ready(Ok(()))
205 }
206
207 fn call(&mut self, req: Self::Request) -> Self::Future {
208 (self.f)(req)
209 }
210}
211
212impl<F, Fut, Req, Res, Err, Cfg> ServiceFactory for FnServiceFactory<F, Fut, Req, Res, Err, Cfg>
213where
214 F: FnMut(Req) -> Fut + Clone,
215 Fut: Future<Output = Result<Res, Err>>,
216{
217 type Request = Req;
218 type Response = Res;
219 type Error = Err;
220
221 type Config = Cfg;
222 type Service = FnService<F, Fut, Req, Res, Err>;
223 type InitError = ();
224 type Future = Ready<Result<Self::Service, Self::InitError>>;
225
226 fn new_service(&self, _: Cfg) -> Self::Future {
227 ok(FnService::new(self.f.clone()))
228 }
229}
230
231impl<F, Fut, Req, Res, Err, Cfg>
232 IntoServiceFactory<FnServiceFactory<F, Fut, Req, Res, Err, Cfg>> for F
233where
234 F: Fn(Req) -> Fut + Clone,
235 Fut: Future<Output = Result<Res, Err>>,
236{
237 fn into_factory(self) -> FnServiceFactory<F, Fut, Req, Res, Err, Cfg> {
238 FnServiceFactory::new(self)
239 }
240}
241
242pub struct FnServiceConfig<F, Fut, Cfg, Srv, Err>
244where
245 F: Fn(Cfg) -> Fut,
246 Fut: Future<Output = Result<Srv, Err>>,
247 Srv: Service,
248{
249 f: F,
250 _t: PhantomData<(Fut, Cfg, Srv, Err)>,
251}
252
253impl<F, Fut, Cfg, Srv, Err> FnServiceConfig<F, Fut, Cfg, Srv, Err>
254where
255 F: Fn(Cfg) -> Fut,
256 Fut: Future<Output = Result<Srv, Err>>,
257 Srv: Service,
258{
259 fn new(f: F) -> Self {
260 FnServiceConfig { f, _t: PhantomData }
261 }
262}
263
264impl<F, Fut, Cfg, Srv, Err> Clone for FnServiceConfig<F, Fut, Cfg, Srv, Err>
265where
266 F: Fn(Cfg) -> Fut + Clone,
267 Fut: Future<Output = Result<Srv, Err>>,
268 Srv: Service,
269{
270 fn clone(&self) -> Self {
271 FnServiceConfig {
272 f: self.f.clone(),
273 _t: PhantomData,
274 }
275 }
276}
277
278impl<F, Fut, Cfg, Srv, Err> ServiceFactory for FnServiceConfig<F, Fut, Cfg, Srv, Err>
279where
280 F: Fn(Cfg) -> Fut,
281 Fut: Future<Output = Result<Srv, Err>>,
282 Srv: Service,
283{
284 type Request = Srv::Request;
285 type Response = Srv::Response;
286 type Error = Srv::Error;
287
288 type Config = Cfg;
289 type Service = Srv;
290 type InitError = Err;
291 type Future = Fut;
292
293 fn new_service(&self, cfg: Cfg) -> Self::Future {
294 (self.f)(cfg)
295 }
296}
297
298pub struct FnServiceNoConfig<F, C, S, R, E>
300where
301 F: Fn() -> R,
302 S: Service,
303 R: Future<Output = Result<S, E>>,
304{
305 f: F,
306 _t: PhantomData<C>,
307}
308
309impl<F, C, S, R, E> FnServiceNoConfig<F, C, S, R, E>
310where
311 F: Fn() -> R,
312 R: Future<Output = Result<S, E>>,
313 S: Service,
314{
315 fn new(f: F) -> Self {
316 Self { f, _t: PhantomData }
317 }
318}
319
320impl<F, C, S, R, E> ServiceFactory for FnServiceNoConfig<F, C, S, R, E>
321where
322 F: Fn() -> R,
323 R: Future<Output = Result<S, E>>,
324 S: Service,
325{
326 type Request = S::Request;
327 type Response = S::Response;
328 type Error = S::Error;
329 type Service = S;
330 type Config = C;
331 type InitError = E;
332 type Future = R;
333
334 fn new_service(&self, _: C) -> Self::Future {
335 (self.f)()
336 }
337}
338
339impl<F, C, S, R, E> Clone for FnServiceNoConfig<F, C, S, R, E>
340where
341 F: Fn() -> R + Clone,
342 R: Future<Output = Result<S, E>>,
343 S: Service,
344{
345 fn clone(&self) -> Self {
346 Self::new(self.f.clone())
347 }
348}
349
350impl<F, C, S, R, E> IntoServiceFactory<FnServiceNoConfig<F, C, S, R, E>> for F
351where
352 F: Fn() -> R,
353 R: Future<Output = Result<S, E>>,
354 S: Service,
355{
356 fn into_factory(self) -> FnServiceNoConfig<F, C, S, R, E> {
357 FnServiceNoConfig::new(self)
358 }
359}
360
361#[cfg(test)]
362mod tests {
363 use std::task::Poll;
364
365 use futures_util::future::{lazy, ok};
366
367 use super::*;
368 use crate::{Service, ServiceFactory};
369
370 #[actix_rt::test]
371 async fn test_fn_service() {
372 let new_srv = fn_service(|()| ok::<_, ()>("srv"));
373
374 let mut srv = new_srv.new_service(()).await.unwrap();
375 let res = srv.call(()).await;
376 assert_eq!(lazy(|cx| srv.poll_ready(cx)).await, Poll::Ready(Ok(())));
377 assert!(res.is_ok());
378 assert_eq!(res.unwrap(), "srv");
379 }
380
381 #[actix_rt::test]
382 async fn test_fn_service_service() {
383 let mut srv = fn_service(|()| ok::<_, ()>("srv"));
384
385 let res = srv.call(()).await;
386 assert_eq!(lazy(|cx| srv.poll_ready(cx)).await, Poll::Ready(Ok(())));
387 assert!(res.is_ok());
388 assert_eq!(res.unwrap(), "srv");
389 }
390
391 #[actix_rt::test]
392 async fn test_fn_service_with_config() {
393 let new_srv = fn_factory_with_config(|cfg: usize| {
394 ok::<_, ()>(fn_service(move |()| ok::<_, ()>(("srv", cfg))))
395 });
396
397 let mut srv = new_srv.new_service(1).await.unwrap();
398 let res = srv.call(()).await;
399 assert_eq!(lazy(|cx| srv.poll_ready(cx)).await, Poll::Ready(Ok(())));
400 assert!(res.is_ok());
401 assert_eq!(res.unwrap(), ("srv", 1));
402 }
403}