boluo_core/
handler.rs

1//! 可用于处理请求并返回响应的异步函数。
2
3use std::marker::PhantomData;
4
5use crate::BoxError;
6use crate::extract::FromRequest;
7use crate::request::Request;
8use crate::response::{IntoResponse, Response};
9use crate::service::Service;
10
11/// 将给定的处理程序转换为 [`Service`]。
12///
13/// # 例子
14///
15/// ```
16/// use boluo_core::handler::handler_fn;
17///
18/// async fn hello() -> &'static str {
19///     "Hello, World!"
20/// }
21///
22/// let service = handler_fn(hello);
23/// ```
24pub fn handler_fn<F, T>(f: F) -> HandlerFn<F, T>
25where
26    HandlerFn<F, T>: Service<Request>,
27{
28    HandlerFn {
29        f,
30        _marker: Default::default(),
31    }
32}
33
34/// 将给定的处理程序转换为 [`Service`]。
35pub struct HandlerFn<F, T> {
36    f: F,
37    _marker: PhantomData<fn(T) -> T>,
38}
39
40impl<F: Clone, T> Clone for HandlerFn<F, T> {
41    fn clone(&self) -> Self {
42        Self {
43            f: self.f.clone(),
44            _marker: Default::default(),
45        }
46    }
47}
48
49impl<F: Copy, T> Copy for HandlerFn<F, T> {}
50
51impl<F, T> std::fmt::Debug for HandlerFn<F, T> {
52    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
53        f.debug_struct("HandlerFn")
54            .field("f", &std::any::type_name::<F>())
55            .finish()
56    }
57}
58
59impl<F, Fut> Service<Request> for HandlerFn<F, ()>
60where
61    F: Fn() -> Fut + Send + Sync,
62    Fut: Future + Send,
63    Fut::Output: IntoResponse,
64{
65    type Response = Response;
66    type Error = BoxError;
67
68    async fn call(&self, _: Request) -> Result<Self::Response, Self::Error> {
69        (self.f)().await.into_response().map_err(Into::into)
70    }
71}
72
73impl<F, Fut> Service<Request> for HandlerFn<F, Request>
74where
75    F: Fn(Request) -> Fut + Send + Sync,
76    Fut: Future + Send,
77    Fut::Output: IntoResponse,
78{
79    type Response = Response;
80    type Error = BoxError;
81
82    async fn call(&self, req: Request) -> Result<Self::Response, Self::Error> {
83        (self.f)(req).await.into_response().map_err(Into::into)
84    }
85}
86
87macro_rules! handler_tuples {
88    ($($ty:ident),*) => {
89        #[allow(non_snake_case)]
90        impl<F, Fut, $($ty,)*> Service<Request> for HandlerFn<F, ($($ty,)*)>
91        where
92            F: Fn($($ty,)*) -> Fut + Send + Sync,
93            Fut: Future + Send,
94            Fut::Output: IntoResponse,
95            $($ty: FromRequest + Send,)*
96            $(<$ty as FromRequest>::Error: Into<BoxError>,)*
97        {
98            type Response = Response;
99            type Error = BoxError;
100
101            async fn call(&self, mut req: Request) -> Result<Self::Response, Self::Error> {
102                $(
103                    let $ty = $ty::from_request(&mut req).await.map_err(Into::into)?;
104                )*
105                (self.f)($($ty,)*).await.into_response().map_err(Into::into)
106            }
107        }
108
109        #[allow(non_snake_case)]
110        impl<F, Fut, $($ty,)*> Service<Request> for HandlerFn<F, ($($ty,)* Request)>
111        where
112            F: Fn($($ty,)* Request) -> Fut + Send + Sync,
113            Fut: Future + Send,
114            Fut::Output: IntoResponse,
115            $($ty: FromRequest + Send,)*
116            $(<$ty as FromRequest>::Error: Into<BoxError>,)*
117        {
118            type Response = Response;
119            type Error = BoxError;
120
121            async fn call(&self, mut req: Request) -> Result<Self::Response, Self::Error> {
122                $(
123                    let $ty = $ty::from_request(&mut req).await.map_err(Into::into)?;
124                )*
125                (self.f)($($ty,)* req).await.into_response().map_err(Into::into)
126            }
127        }
128    };
129}
130
131handler_tuples!(T1);
132handler_tuples!(T1, T2);
133handler_tuples!(T1, T2, T3);
134handler_tuples!(T1, T2, T3, T4);
135handler_tuples!(T1, T2, T3, T4, T5);
136handler_tuples!(T1, T2, T3, T4, T5, T6);
137handler_tuples!(T1, T2, T3, T4, T5, T6, T7);
138handler_tuples!(T1, T2, T3, T4, T5, T6, T7, T8);
139handler_tuples!(T1, T2, T3, T4, T5, T6, T7, T8, T9);
140handler_tuples!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10);
141handler_tuples!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11);
142handler_tuples!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12);
143handler_tuples!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13);
144handler_tuples!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14);
145handler_tuples!(
146    T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15
147);
148handler_tuples!(
149    T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16
150);