use crate::{context::Context, error::Result, response::Response};
use std::future::Future;
use std::pin::Pin;
use std::sync::Arc;
pub type BoxedHandler =
Arc<dyn Fn(Context) -> Pin<Box<dyn Future<Output = Result<Response>> + Send>> + Send + Sync>;
pub trait IntoHandler<Args> {
fn into_handler(self) -> BoxedHandler;
}
use crate::extract::FromRequest;
macro_rules! impl_into_handler {
( $( $ty:ident ),* ) => {
impl<F, Fut, $( $ty ),*> IntoHandler<( $( $ty, )* )> for F
where
F: Fn( $( $ty ),* ) -> Fut + Clone + Send + Sync + 'static,
Fut: Future<Output = Result<Response>> + Send + 'static,
$( $ty: FromRequest + Send + 'static, )*
{
#[allow(non_snake_case, unused_variables, unused_mut)]
fn into_handler(self) -> BoxedHandler {
Arc::new(move |ctx: Context| {
let handler = self.clone();
Box::pin(async move {
$( let $ty = <$ty as FromRequest>::from_request(&ctx).await?; )*
handler( $( $ty ),* ).await
})
})
}
}
};
}
impl_into_handler!();
impl_into_handler!(T1);
impl_into_handler!(T1, T2);
impl_into_handler!(T1, T2, T3);
impl_into_handler!(T1, T2, T3, T4);
impl_into_handler!(T1, T2, T3, T4, T5);
impl_into_handler!(T1, T2, T3, T4, T5, T6);
impl_into_handler!(T1, T2, T3, T4, T5, T6, T7);
impl_into_handler!(T1, T2, T3, T4, T5, T6, T7, T8);
#[cfg(test)]
mod tests {
use super::*;
use crate::response;
#[tokio::test]
async fn test_handler_trait() {
let _handler =
(|_ctx: Context| async move { response::helpers::text("Hello") }).into_handler();
}
}