safe-vk 1.2.2

A simple library to create your own vk bot for conversations
Documentation
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,))
            }
        }

        // This impl must not be generic over M, otherwise it would conflict with the blanket
        // implementation of `FromRequest<S, Mut>` for `T: FromRequestParts<S>`.
        #[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,
        }
    }
}