use std::{error::Error, fmt, future::Future, sync::Arc};
use crate::{
core::{context::Context, convert::TryFromInput},
types::Update,
};
#[cfg(test)]
mod tests;
pub trait Handler<I>: Clone + Send
where
I: TryFromInput,
{
type Output: Send;
fn handle(&self, input: I) -> impl Future<Output = Self::Output> + Send;
}
macro_rules! impl_fn {
($($I:ident),+) => {
#[allow(non_snake_case)]
impl<X, $($I,)+ R> Handler<($($I,)+)> for X
where
X: Fn($($I,)+) -> R + Clone + Send + Sync,
($($I,)+): TryFromInput,
R: Future + Send,
R::Output: Send
{
type Output = R::Output;
async fn handle(&self, ($($I,)+): ($($I,)+)) -> Self::Output {
(self)($($I,)+).await
}
}
};
}
impl_fn!(A);
impl_fn!(A, B);
impl_fn!(A, B, C);
impl_fn!(A, B, C, D);
impl_fn!(A, B, C, D, E);
impl_fn!(A, B, C, D, E, F);
impl_fn!(A, B, C, D, E, F, G);
impl_fn!(A, B, C, D, E, F, G, H);
impl_fn!(A, B, C, D, E, F, G, H, I);
impl_fn!(A, B, C, D, E, F, G, H, I, J);
#[derive(Clone, Debug)]
pub struct HandlerInput {
pub update: Update,
pub context: Arc<Context>,
}
impl From<Update> for HandlerInput {
fn from(update: Update) -> Self {
HandlerInput {
update,
context: Arc::new(Default::default()),
}
}
}
pub struct HandlerError(Box<dyn Error + Send>);
impl HandlerError {
pub fn new<E>(err: E) -> Self
where
E: Error + Send + 'static,
{
Self(Box::new(err))
}
}
impl fmt::Debug for HandlerError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&self.0, f)
}
}
impl fmt::Display for HandlerError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self.0, f)
}
}
impl Error for HandlerError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
self.0.source()
}
}
pub type HandlerResult = Result<(), HandlerError>;
pub trait IntoHandlerResult {
fn into_result(self) -> HandlerResult;
}
impl IntoHandlerResult for () {
fn into_result(self) -> HandlerResult {
Ok(self)
}
}
impl<E> IntoHandlerResult for Result<(), E>
where
E: Error + Send + 'static,
{
fn into_result(self) -> HandlerResult {
self.map_err(HandlerError::new)
}
}