httpz/
generic_endpoint.rs1use http::Method;
2use std::future::Future;
3
4use crate::{Endpoint, HttpEndpoint, HttpResponse, Request};
5
6pub trait EndpointFn<'this>
8where
9 Self: Send + Sync + 'this,
10{
11 type Response: HttpResponse;
13
14 type Fut: Future<Output = Self::Response> + Send + 'this;
16
17 fn call(&self, req: Request) -> Self::Fut;
19}
20
21impl<'this, TFut, TFunc, TRes> EndpointFn<'this> for TFunc
22where
23 TFunc: Fn(Request) -> TFut + Send + Sync + 'this,
24 TFut: Future<Output = TRes> + Send + 'this,
25 TRes: HttpResponse,
26{
27 type Response = TRes;
28 type Fut = TFut;
29
30 fn call(&self, req: Request) -> Self::Fut {
31 self(req)
32 }
33}
34
35pub struct GenericEndpoint<TMethods, TEndpointFn, TUrl>
37where
38 TMethods: AsRef<[Method]> + Send + Sync + 'static,
39 TEndpointFn: for<'this> EndpointFn<'this>,
40 TUrl: AsRef<str> + Send + Sync + 'static,
41{
42 methods: Option<TMethods>,
43 func: TEndpointFn,
44 url: Option<TUrl>,
45}
46
47impl<TMethods, TEndpointFn, TUrl> Clone for GenericEndpoint<TMethods, TEndpointFn, TUrl>
48where
49 TMethods: AsRef<[Method]> + Clone + Send + Sync + 'static,
50 TEndpointFn: for<'this> EndpointFn<'this> + Clone,
51 TUrl: AsRef<str> + Clone + Send + Sync + 'static,
52{
53 fn clone(&self) -> Self {
54 Self {
55 methods: self.methods.clone(),
56 func: self.func.clone(),
57 url: self.url.clone(),
58 }
59 }
60}
61
62impl<TMethods, TEndpointFn, TUrl> GenericEndpoint<TMethods, TEndpointFn, TUrl>
63where
64 TMethods: AsRef<[Method]> + Send + Sync + 'static,
65 TEndpointFn: for<'this> EndpointFn<'this>,
66 TUrl: AsRef<str> + Send + Sync + 'static,
67{
68 pub fn new(url: TUrl, methods: TMethods, func: TEndpointFn) -> Endpoint<Self> {
70 Endpoint::from_endpoint(Self::new_raw(url, methods, func))
71 }
72
73 pub fn new_raw(url: TUrl, methods: TMethods, func: TEndpointFn) -> Self {
75 Self {
76 methods: Some(methods),
77 func,
78 url: Some(url),
79 }
80 }
81}
82
83impl<TMethods, TEndpointFn, TUrl> HttpEndpoint for GenericEndpoint<TMethods, TEndpointFn, TUrl>
84where
85 TMethods: AsRef<[Method]> + Send + Sync + 'static,
86 TEndpointFn: for<'this> EndpointFn<'this>,
87 TUrl: AsRef<str> + Send + Sync + 'static,
88{
89 type Routes = TMethods;
90 type Url = TUrl;
91 type EndpointFn = TEndpointFn;
92
93 fn register(&mut self) -> (Self::Url, Self::Routes) {
94 (
95 match self.url.take() {
96 Some(url) => url,
97 None => unreachable!(),
98 },
99 match self.methods.take() {
100 Some(methods) => methods,
101 None => unreachable!(),
102 },
103 )
104 }
105
106 fn handler(&self, req: Request) -> <Self::EndpointFn as EndpointFn<'_>>::Fut {
107 self.func.call(req)
108 }
109}