use alloc::boxed::Box;
use core::future::Future;
use crate::{BoxFuture, FromRoute, RouteContext, RouteResult};
pub trait Handler<T, S, R>: Clone + 'static {
fn call(self, context: RouteContext, state: S) -> BoxFuture<RouteResult<R>>;
}
pub trait SyncHandler<T, S, R>: Clone + 'static {
fn call_sync(self, context: RouteContext, state: S) -> RouteResult<R>;
}
impl<Func, Fut, Out, S, R> Handler<(), S, R> for Func
where
Func: FnOnce() -> Fut + Clone + 'static,
Fut: Future<Output = Out> + 'static,
Out: Into<R>,
S: 'static,
R: 'static,
{
fn call(self, _context: RouteContext, _state: S) -> BoxFuture<RouteResult<R>> {
let future = self();
Box::pin(async move { Ok(future.await.into()) })
}
}
impl<Func, Out, S, R> SyncHandler<(), S, R> for Func
where
Func: FnOnce() -> Out + Clone + 'static,
Out: Into<R>,
S: 'static,
R: 'static,
{
fn call_sync(self, _context: RouteContext, _state: S) -> RouteResult<R> {
Ok(self().into())
}
}
macro_rules! impl_handler {
($($ty:ident),+) => {
impl<Func, Fut, Out, S, R, $($ty,)+> Handler<($($ty,)+), S, R> for Func
where
Func: FnOnce($($ty),+) -> Fut + Clone + 'static,
Fut: Future<Output = Out> + 'static,
Out: Into<R>,
S: Clone + 'static,
R: 'static,
$($ty: FromRoute<S>,)+
{
#[allow(non_snake_case)]
fn call(self, context: RouteContext, state: S) -> BoxFuture<RouteResult<R>> {
Box::pin(async move {
$(
let $ty = $ty::from_route(&context, &state)?;
)+
Ok(self($($ty),+).await.into())
})
}
}
};
}
macro_rules! impl_sync_handler {
($($ty:ident),+) => {
impl<Func, Out, S, R, $($ty,)+> SyncHandler<($($ty,)+), S, R> for Func
where
Func: FnOnce($($ty),+) -> Out + Clone + 'static,
Out: Into<R>,
S: Clone + 'static,
R: 'static,
$($ty: FromRoute<S>,)+
{
#[allow(non_snake_case)]
fn call_sync(self, context: RouteContext, state: S) -> RouteResult<R> {
$(
let $ty = $ty::from_route(&context, &state)?;
)+
Ok(self($($ty),+).into())
}
}
};
}
impl_handler!(A);
impl_handler!(A, B);
impl_handler!(A, B, C);
impl_handler!(A, B, C, D);
impl_handler!(A, B, C, D, E);
impl_handler!(A, B, C, D, E, F);
impl_handler!(A, B, C, D, E, F, G);
impl_handler!(A, B, C, D, E, F, G, H);
impl_handler!(A, B, C, D, E, F, G, H, I);
impl_handler!(A, B, C, D, E, F, G, H, I, J);
impl_handler!(A, B, C, D, E, F, G, H, I, J, K);
impl_handler!(A, B, C, D, E, F, G, H, I, J, K, L);
impl_handler!(A, B, C, D, E, F, G, H, I, J, K, L, M);
impl_handler!(A, B, C, D, E, F, G, H, I, J, K, L, M, N);
impl_handler!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O);
impl_handler!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P);
impl_sync_handler!(A);
impl_sync_handler!(A, B);
impl_sync_handler!(A, B, C);
impl_sync_handler!(A, B, C, D);
impl_sync_handler!(A, B, C, D, E);
impl_sync_handler!(A, B, C, D, E, F);
impl_sync_handler!(A, B, C, D, E, F, G);
impl_sync_handler!(A, B, C, D, E, F, G, H);
impl_sync_handler!(A, B, C, D, E, F, G, H, I);
impl_sync_handler!(A, B, C, D, E, F, G, H, I, J);
impl_sync_handler!(A, B, C, D, E, F, G, H, I, J, K);
impl_sync_handler!(A, B, C, D, E, F, G, H, I, J, K, L);
impl_sync_handler!(A, B, C, D, E, F, G, H, I, J, K, L, M);
impl_sync_handler!(A, B, C, D, E, F, G, H, I, J, K, L, M, N);
impl_sync_handler!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O);
impl_sync_handler!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P);