xitca_web/handler/
sync.rs1#![allow(non_snake_case)]
2
3use core::{convert::Infallible, marker::PhantomData};
4
5use super::{FromRequest, Responder};
6
7use xitca_service::{FnService, Service, fn_build};
8
9pub fn handler_sync_service<Arg, F, T>(func: F) -> FnService<impl AsyncFn(Arg) -> FnServiceOutput<F, T>>
38where
39 F: Closure<T> + Send + Clone,
40{
41 fn_build(async move |_| {
42 Ok(HandlerServiceSync {
43 func: func.clone(),
44 _p: PhantomData,
45 })
46 })
47}
48
49type FnServiceOutput<F, T> = Result<HandlerServiceSync<F, T>, Infallible>;
50
51pub struct HandlerServiceSync<F, T> {
52 func: F,
53 _p: PhantomData<T>,
54}
55
56impl<F, Req, T, O> Service<Req> for HandlerServiceSync<F, T>
57where
58 T: FromRequest<'static, Req>,
60 F: Closure<T> + Send + Clone + 'static,
62 F: for<'a> Closure<T::Type<'a>, Output = O>,
63 O: Responder<Req> + Send + 'static,
64 for<'a> T::Type<'a>: Send + 'static,
65 T::Error: From<O::Error>,
66{
67 type Response = O::Response;
68 type Error = T::Error;
69
70 async fn call(&self, req: Req) -> Result<Self::Response, Self::Error> {
71 let extract = T::Type::<'_>::from_request(&req).await?;
72 let func = self.func.clone();
73 let res = tokio::task::spawn_blocking(move || func.call(extract)).await.unwrap();
74 res.respond(req).await.map_err(Into::into)
75 }
76}
77
78#[doc(hidden)]
79pub trait Closure<Arg> {
81 type Output;
82
83 fn call(&self, arg: Arg) -> Self::Output;
84}
85
86macro_rules! closure_impl {
87 ($($arg: ident),*) => {
88 impl<Func, O, $($arg,)*> Closure<($($arg,)*)> for Func
89 where
90 Func: Fn($($arg),*) -> O,
91 {
92 type Output = O;
93
94 #[inline]
95 fn call(&self, ($($arg,)*): ($($arg,)*)) -> Self::Output {
96 self($($arg,)*)
97 }
98 }
99 }
100}
101
102closure_impl! {}
103closure_impl! { A }
104closure_impl! { A, B }
105closure_impl! { A, B, C }
106closure_impl! { A, B, C, D }
107closure_impl! { A, B, C, D, E }
108closure_impl! { A, B, C, D, E, F }
109closure_impl! { A, B, C, D, E, F, G }
110closure_impl! { A, B, C, D, E, F, G, H }
111closure_impl! { A, B, C, D, E, F, G, H, I }