Skip to main content

flow_bot/base/
handler.rs

1use crate::{base::extract::FromEvent, event::BotEvent};
2use async_trait::async_trait;
3use std::{convert::Infallible, future::Future, ops::FromResidual};
4
5use super::context::BotContext;
6
7pub enum HandlerControl {
8    Skip,
9    Continue,
10    Block,
11}
12
13impl<E> FromResidual<Result<Infallible, E>> for HandlerControl {
14    fn from_residual(residual: Result<Infallible, E>) -> Self {
15        match residual {
16            Err(_) => HandlerControl::Skip,
17        }
18    }
19}
20
21impl FromResidual<Option<Infallible>> for HandlerControl {
22    fn from_residual(residual: Option<Infallible>) -> Self {
23        match residual {
24            None => HandlerControl::Skip,
25        }
26    }
27}
28
29#[async_trait]
30pub trait Handler<T> {
31    async fn handle(&self, context: BotContext, event: BotEvent) -> HandlerControl;
32}
33
34macro_rules! impl_handler {
35    ([$($ty:ident),*]) => {
36        #[allow(unused_variables, unused_mut,unused_parens,non_snake_case)]
37        #[async_trait]
38        impl<F,Fut, $($ty),*> Handler<($($ty),*)> for F
39        where
40            F: Fn($($ty),*) -> Fut + Send + Sync + 'static,
41            Fut: Future<Output = HandlerControl> + Send + 'static,
42            $($ty: FromEvent+Send),*
43        {
44            async fn handle(&self, context: BotContext, event: BotEvent) -> HandlerControl {
45                match ($($ty::from_event(context.clone(), event.clone()).await,)*) {
46                    ($(Some($ty),)*) => self($($ty),*).await,
47                    _ => HandlerControl::Skip,
48                }
49            }
50        }
51    };
52}
53
54#[async_trait]
55pub(crate) trait ErasedHandler: Send + Sync {
56    async fn call(&self, context: BotContext, event: BotEvent) -> HandlerControl;
57}
58
59pub(crate) struct HWrapped<T, H> {
60    pub handler: H,
61    pub _phantom: std::marker::PhantomData<T>,
62}
63
64#[async_trait]
65impl<H, T> ErasedHandler for HWrapped<T, H>
66where
67    H: Handler<T> + Send + Sync + 'static,
68    T: Send + Sync + 'static,
69{
70    async fn call(&self, context: BotContext, event: BotEvent) -> HandlerControl {
71        self.handler.handle(context, event).await
72    }
73}
74
75macro_rules! all_tuples {
76    ($macro:ident) => {
77        $macro!([T1]);
78        $macro!([T1, T2]);
79        $macro!([T1, T2, T3]);
80        $macro!([T1, T2, T3, T4]);
81        $macro!([T1, T2, T3, T4, T5]);
82        $macro!([T1, T2, T3, T4, T5, T6]);
83        $macro!([T1, T2, T3, T4, T5, T6, T7]);
84        $macro!([T1, T2, T3, T4, T5, T6, T7, T8]);
85        $macro!([T1, T2, T3, T4, T5, T6, T7, T8, T9]);
86        $macro!([T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]);
87        $macro!([T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11]);
88        $macro!([T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12]);
89        $macro!([T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13]);
90        $macro!([T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14]);
91        $macro!([
92            T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15
93        ]);
94    };
95}
96
97all_tuples!(impl_handler);