use std::future::Future;
use std::marker::PhantomData;
use crate::extract::FromRequest;
use crate::request::Request;
use crate::response::{IntoResponse, Response};
use crate::service::Service;
use crate::BoxError;
pub fn handler_fn<F, T>(f: F) -> HandlerFn<F, T>
where
HandlerFn<F, T>: Service<Request>,
{
HandlerFn {
f,
_marker: Default::default(),
}
}
pub struct HandlerFn<F, T> {
f: F,
_marker: PhantomData<fn(T) -> T>,
}
impl<F: Clone, T> Clone for HandlerFn<F, T> {
fn clone(&self) -> Self {
Self {
f: self.f.clone(),
_marker: Default::default(),
}
}
}
impl<F: Copy, T> Copy for HandlerFn<F, T> {}
impl<F, T> std::fmt::Debug for HandlerFn<F, T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("HandlerFn")
.field("f", &std::any::type_name::<F>())
.finish()
}
}
impl<F, Fut> Service<Request> for HandlerFn<F, ()>
where
F: Fn() -> Fut + Send + Sync,
Fut: Future + Send,
Fut::Output: IntoResponse,
{
type Response = Response;
type Error = BoxError;
async fn call(&self, _: Request) -> Result<Self::Response, Self::Error> {
(self.f)().await.into_response().map_err(Into::into)
}
}
impl<F, Fut> Service<Request> for HandlerFn<F, Request>
where
F: Fn(Request) -> Fut + Send + Sync,
Fut: Future + Send,
Fut::Output: IntoResponse,
{
type Response = Response;
type Error = BoxError;
async fn call(&self, req: Request) -> Result<Self::Response, Self::Error> {
(self.f)(req).await.into_response().map_err(Into::into)
}
}
macro_rules! handler_tuples {
($($ty:ident),*) => {
#[allow(non_snake_case)]
impl<F, Fut, $($ty,)*> Service<Request> for HandlerFn<F, ($($ty,)*)>
where
F: Fn($($ty,)*) -> Fut + Send + Sync,
Fut: Future + Send,
Fut::Output: IntoResponse,
$($ty: FromRequest + Send,)*
$(<$ty as FromRequest>::Error: Into<BoxError>,)*
{
type Response = Response;
type Error = BoxError;
async fn call(&self, mut req: Request) -> Result<Self::Response, Self::Error> {
$(
let $ty = $ty::from_request(&mut req).await.map_err(Into::into)?;
)*
(self.f)($($ty,)*).await.into_response().map_err(Into::into)
}
}
#[allow(non_snake_case)]
impl<F, Fut, $($ty,)*> Service<Request> for HandlerFn<F, ($($ty,)* Request)>
where
F: Fn($($ty,)* Request) -> Fut + Send + Sync,
Fut: Future + Send,
Fut::Output: IntoResponse,
$($ty: FromRequest + Send,)*
$(<$ty as FromRequest>::Error: Into<BoxError>,)*
{
type Response = Response;
type Error = BoxError;
async fn call(&self, mut req: Request) -> Result<Self::Response, Self::Error> {
$(
let $ty = $ty::from_request(&mut req).await.map_err(Into::into)?;
)*
(self.f)($($ty,)* req).await.into_response().map_err(Into::into)
}
}
};
}
handler_tuples!(T1);
handler_tuples!(T1, T2);
handler_tuples!(T1, T2, T3);
handler_tuples!(T1, T2, T3, T4);
handler_tuples!(T1, T2, T3, T4, T5);
handler_tuples!(T1, T2, T3, T4, T5, T6);
handler_tuples!(T1, T2, T3, T4, T5, T6, T7);
handler_tuples!(T1, T2, T3, T4, T5, T6, T7, T8);
handler_tuples!(T1, T2, T3, T4, T5, T6, T7, T8, T9);
handler_tuples!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10);
handler_tuples!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11);
handler_tuples!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12);
handler_tuples!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13);
handler_tuples!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14);
handler_tuples!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15);
handler_tuples!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16);