use std::{
future::Future,
marker::PhantomData,
pin::Pin,
sync::{Arc, Mutex},
};
use crate::extract::{FromUpdate, FromUpdateParts, Parts, Update};
pub trait Handler<T, S>: Clone + Send + Sized + 'static {
type Future: Future<Output = ()> + Send + 'static;
fn call(self, update: Update, state: S, request: Arc<RequestBuilder>) -> Self::Future;
fn with_state(self, state: S) -> HandlerService<Self, T, S> {
HandlerService::new(self, state)
}
}
impl<F, Fut, S> Handler<((),), S> for F
where
F: FnOnce() -> Fut + Clone + Send + 'static,
Fut: Future<Output = ()> + Send,
{
type Future = Pin<Box<dyn Future<Output = ()> + Send>>;
fn call(self, _update: Update, _state: S, _request: Arc<RequestBuilder>) -> Self::Future {
Box::pin(async move { self().await })
}
}
#[rustfmt::skip]
macro_rules! all_the_tuples {
($name:ident) => {
$name!([], T1);
$name!([T1], T2);
$name!([T1, T2], T3);
$name!([T1, T2, T3], T4);
$name!([T1, T2, T3, T4], T5);
$name!([T1, T2, T3, T4, T5], T6);
$name!([T1, T2, T3, T4, T5, T6], T7);
$name!([T1, T2, T3, T4, T5, T6, T7], T8);
$name!([T1, T2, T3, T4, T5, T6, T7, T8], T9);
$name!([T1, T2, T3, T4, T5, T6, T7, T8, T9], T10);
$name!([T1, T2, T3, T4, T5, T6, T7, T8, T9, T10], T11);
$name!([T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11], T12);
$name!([T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12], T13);
$name!([T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13], T14);
$name!([T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14], T15);
$name!([T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15], T16);
};
}
use crate::RequestBuilder;
macro_rules! impl_handler {
(
[$($ty:ident),*], $last:ident
) => {
#[allow(non_snake_case, unused_mut)]
impl<F, Fut, S, M, $($ty,)* $last> Handler<(M, $($ty,)* $last,), S> for F
where
F: FnOnce($($ty,)* $last,) -> Fut + Clone + Send + 'static,
Fut: Future<Output = ()> + Send,
S: Send + Sync + 'static,
$( $ty: FromUpdateParts<S> + Send, )*
$last: FromUpdate<S, M> + Send,
{
type Future = Pin<Box<dyn Future<Output = ()> + Send>>;
fn call(self, update: Update, state: S, request: Arc<RequestBuilder>) -> Self::Future {
Box::pin(async move {
let mut _parts = update.clone().into_parts();
let state = &state;
$(
let $ty = match $ty::from_update_parts(&mut _parts, state, request.clone()).await {
Ok(value) => value,
Err(_) => panic!(),
};
)*
let $last = match $last::from_update(update, state, request).await {
Ok(value) => value,
Err(_) => panic!(),
};
self($($ty,)* $last,).await;
})
}
}
};
}
all_the_tuples!(impl_handler);
macro_rules! impl_from_request {
(
[$($ty:ident),*], $last:ident
) => {
#[allow(non_snake_case, unused_mut, unused_variables)]
impl<S, $($ty,)* $last> FromUpdateParts<S> for ($($ty,)* $last,)
where
$( $ty: FromUpdateParts<S> + Send, )*
$last: FromUpdateParts<S> + Send,
S: Send + Sync,
{
async fn from_update_parts(parts: &mut Parts, state: &S, request: Arc<RequestBuilder>) -> Result<Self, ()> {
$(
let $ty = $ty::from_update_parts(parts, state, request.clone())
.await.unwrap();
)*
let $last = $last::from_update_parts(parts, state, request)
.await.unwrap();
Ok(($($ty,)* $last,))
}
}
#[allow(non_snake_case, unused_mut, unused_variables)]
impl<S, $($ty,)* $last> FromUpdate<S> for ($($ty,)* $last,)
where
$( $ty: FromUpdateParts<S> + Send, )*
$last: FromUpdate<S> + Send,
S: Send + Sync,
{
async fn from_update(req: Update, state: &S, request: Arc<RequestBuilder>) -> Result<Self, ()> {
let mut parts = req.clone().into_parts();
$(
let $ty = $ty::from_update_parts(&mut parts, state, request.clone()).await.unwrap();
)*
let $last = $last::from_update(req, state, request).await.unwrap();
Ok(($($ty,)* $last,))
}
}
};
}
all_the_tuples!(impl_from_request);
pub struct HandlerService<H, T, S> {
handler: H,
state: S,
_marker: PhantomData<fn() -> T>,
}
pub struct MakeErasedHandler<H, S> {
pub handler: H,
pub into_route: fn(H, S) -> Route,
}
impl<H, T, S> HandlerService<H, T, S> {
pub(super) fn new(handler: H, state: S) -> Self {
Self {
handler,
state,
_marker: PhantomData,
}
}
}
pub struct Boxed<S>(pub(crate) Mutex<Box<dyn BoxedIntoHandler<S>>>);
impl<S> Boxed<S>
where
S: Clone + Send + Sync + 'static,
{
pub(crate) fn from_handler<H, T>(handler: H) -> Self
where
H: Handler<T, S> + Sync,
T: 'static,
{
Self(Mutex::new(Box::new(MakeErasedHandler {
handler,
into_route: |handler, state| Route::new(Handler::with_state(handler, state)),
})))
}
}
impl<S> Boxed<S> {
pub(crate) fn into_route(self, state: S) -> Route {
self.0.into_inner().unwrap().into_route(state)
}
}
pub trait BoxedIntoHandler<S>: Send {
fn clone_box(&self) -> Box<dyn BoxedIntoHandler<S>>;
fn into_route(self: Box<Self>, state: S) -> Route;
fn call_with_state(self: Box<Self>, update: Update, state: S);
}
impl<H, S> BoxedIntoHandler<S> for MakeErasedHandler<H, S>
where
H: Clone + Send + 'static,
S: 'static,
{
fn clone_box(&self) -> Box<dyn BoxedIntoHandler<S>> {
Box::new(self.clone())
}
fn into_route(self: Box<Self>, state: S) -> Route {
(self.into_route)(self.handler, state)
}
fn call_with_state(self: Box<Self>, _update: Update, _state: S) {}
}
pub trait Execute: Send {
fn execute(self: Box<Self>, update: Update, request: Arc<RequestBuilder>);
fn clone_box(&self) -> Box<dyn Execute>;
}
pub struct Route(Mutex<Box<dyn Execute>>);
impl Route {
pub fn new<T>(executor: T) -> Self
where
T: Execute + Clone + Send + 'static,
{
Self(Mutex::new(Box::new(executor)))
}
pub fn execute(&self, update: Update, request: Arc<RequestBuilder>) {
self.0.lock().unwrap().clone_box().execute(update, request);
}
}
impl<H, T, S> Execute for HandlerService<H, T, S>
where
H: Handler<T, S> + Clone + Send + Sync + 'static,
T: 'static,
S: Sync + Clone + Send + 'static,
{
fn execute(self: Box<Self>, update: Update, request: Arc<RequestBuilder>) {
let handler = self.handler.clone();
tokio::spawn(
async move { Handler::call(handler, update, self.state.clone(), request).await },
);
}
fn clone_box(&self) -> Box<dyn Execute> {
Box::new(self.clone())
}
}
impl<H, S> Clone for MakeErasedHandler<H, S>
where
H: Clone,
{
fn clone(&self) -> Self {
Self {
handler: self.handler.clone(),
into_route: self.into_route,
}
}
}
impl<S> Clone for Boxed<S> {
fn clone(&self) -> Self {
Self(Mutex::new(self.0.lock().unwrap().clone_box()))
}
}
impl Clone for Route {
fn clone(&self) -> Self {
Self(Mutex::new(self.0.lock().unwrap().clone_box()))
}
}
impl<H, T, S> Clone for HandlerService<H, T, S>
where
H: Clone,
S: Clone,
{
fn clone(&self) -> Self {
Self {
handler: self.handler.clone(),
state: self.state.clone(),
_marker: PhantomData,
}
}
}