Merge pull request #79 from telebofr/handles_type

Simplify 'type Handlers = ...' (dispatchers/filter/mod.rs)
This commit is contained in:
Temirkhan Myrzamadi 2019-11-04 01:19:30 +06:00 committed by GitHub
commit 1df08f02c7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 75 additions and 66 deletions

View file

@ -1,8 +1,4 @@
use std::{ use std::{convert::Infallible, future::Future, pin::Pin};
pin::Pin,
future::Future,
convert::Infallible,
};
use async_trait::async_trait; use async_trait::async_trait;
@ -21,8 +17,7 @@ pub trait ErrorPolicy<E> {
/// # #[tokio::main] /// # #[tokio::main]
/// # async fn main() { /// # async fn main() {
/// use telebofr::dispatching::dispatchers::filter::error_policy::{ /// use telebofr::dispatching::dispatchers::filter::error_policy::{
/// ErrorPolicy, /// ErrorPolicy, Ignore,
/// Ignore,
/// }; /// };
/// ///
/// Ignore.handle_error(()).await; /// Ignore.handle_error(()).await;
@ -39,11 +34,13 @@ where
{ {
async fn handle_error(&self, _: E) async fn handle_error(&self, _: E)
where where
E: 'async_trait E: 'async_trait,
{} {
}
} }
/// Error policy that silently ignores all errors that can never happen (e.g.: [`!`] or [`Infallible`]) /// Error policy that silently ignores all errors that can never happen (e.g.:
/// [`!`] or [`Infallible`])
/// ///
/// ## Examples /// ## Examples
/// ``` /// ```
@ -68,8 +65,7 @@ where
/// ///
/// ```compile_fail /// ```compile_fail
/// use telebofr::dispatching::dispatchers::filter::error_policy::{ /// use telebofr::dispatching::dispatchers::filter::error_policy::{
/// ErrorPolicy, /// ErrorPolicy, IgnoreSafe,
/// IgnoreSafe,
/// }; /// };
/// ///
/// IgnoreSafe.handle_error(0); /// IgnoreSafe.handle_error(0);
@ -90,7 +86,7 @@ pub struct IgnoreSafe;
impl ErrorPolicy<!> for IgnoreSafe { impl ErrorPolicy<!> for IgnoreSafe {
async fn handle_error(&self, never: !) async fn handle_error(&self, never: !)
where where
!: 'async_trait !: 'async_trait,
{ {
never never
} }
@ -100,7 +96,7 @@ impl ErrorPolicy<!> for IgnoreSafe {
impl ErrorPolicy<Infallible> for IgnoreSafe { impl ErrorPolicy<Infallible> for IgnoreSafe {
async fn handle_error(&self, inf: Infallible) async fn handle_error(&self, inf: Infallible)
where where
Infallible: 'async_trait Infallible: 'async_trait,
{ {
match inf {} match inf {}
} }
@ -114,9 +110,7 @@ impl ErrorPolicy<Infallible> for IgnoreSafe {
/// # async fn main() { /// # async fn main() {
/// use telebofr::dispatching::dispatchers::filter::error_policy::ErrorPolicy; /// use telebofr::dispatching::dispatchers::filter::error_policy::ErrorPolicy;
/// ///
/// let closure = |e: i32| async move { /// let closure = |e: i32| async move { eprintln!("Error code{}", e) };
/// eprintln!("Error code{}", e)
/// };
/// ///
/// closure.handle_error(404).await; /// closure.handle_error(404).await;
/// # } /// # }
@ -127,11 +121,14 @@ where
Fut: Future<Output = ()> + Send, Fut: Future<Output = ()> + Send,
E: Send, E: Send,
{ {
fn handle_error<'s, 'async_trait>(&'s self, error: E) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>> fn handle_error<'s, 'async_trait>(
&'s self,
error: E,
) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
where where
's: 'async_trait, 's: 'async_trait,
Self: 'async_trait, Self: 'async_trait,
E: 'async_trait E: 'async_trait,
{ {
Box::pin(async move { self(error).await }) Box::pin(async move { self(error).await })
} }

View file

@ -12,8 +12,25 @@ use crate::{
pub mod error_policy; pub mod error_policy;
type Handlers<'a, T, E> = struct FilterAndHandler<'a, T, E> {
Vec<(Box<dyn Filter<T> + 'a>, Box<dyn Handler<'a, T, E> + 'a>)>; filter: Box<dyn Filter<T> + 'a>,
handler: Box<dyn Handler<'a, T, E> + 'a>,
}
impl<'a, T, E> FilterAndHandler<'a, T, E> {
fn new<F, H>(filter: F, handler: H) -> Self
where
F: Filter<T> + 'a,
H: Handler<'a, T, E> + 'a,
{
FilterAndHandler {
filter: Box::new(filter),
handler: Box::new(handler),
}
}
}
type FiltersAndHandlers<'a, T, E> = Vec<FilterAndHandler<'a, T, E>>;
/// Dispatcher that dispatches updates from telegram. /// Dispatcher that dispatches updates from telegram.
/// ///
@ -36,12 +53,14 @@ type Handlers<'a, T, E> =
/// use std::convert::Infallible; /// use std::convert::Infallible;
/// ///
/// use telebofr::{ /// use telebofr::{
/// Bot,
/// types::Message,
/// dispatching::{ /// dispatching::{
/// dispatchers::filter::{error_policy::ErrorPolicy, FilterDispatcher}, /// dispatchers::filter::{
/// error_policy::ErrorPolicy, FilterDispatcher,
/// },
/// updater::polling, /// updater::polling,
/// }, /// },
/// types::Message,
/// Bot,
/// }; /// };
/// ///
/// async fn handle_edited_message(mes: Message) { /// async fn handle_edited_message(mes: Message) {
@ -67,16 +86,18 @@ type Handlers<'a, T, E> =
/// ``` /// ```
/// ///
/// [`std::fmt::Debug`]: std::fmt::Debug /// [`std::fmt::Debug`]: std::fmt::Debug
/// [Custom error policy]: crate::dispatching::filter::error_policy::ErrorPolicy::Custom /// [Custom error policy]:
/// [updater]: crate::dispatching::updater /// crate::dispatching::filter::error_policy::ErrorPolicy::Custom [updater]:
/// crate::dispatching::updater
pub struct FilterDispatcher<'a, E, Ep> { pub struct FilterDispatcher<'a, E, Ep> {
message_handlers: Handlers<'a, Message, E>, message_handlers: FiltersAndHandlers<'a, Message, E>,
edited_message_handlers: Handlers<'a, Message, E>, edited_message_handlers: FiltersAndHandlers<'a, Message, E>,
channel_post_handlers: Handlers<'a, Message, E>, channel_post_handlers: FiltersAndHandlers<'a, Message, E>,
edited_channel_post_handlers: Handlers<'a, Message, E>, edited_channel_post_handlers: FiltersAndHandlers<'a, Message, E>,
inline_query_handlers: Handlers<'a, (), E>, inline_query_handlers: FiltersAndHandlers<'a, (), E>,
chosen_inline_result_handlers: Handlers<'a, ChosenInlineResult, E>, chosen_inline_result_handlers:
callback_query_handlers: Handlers<'a, CallbackQuery, E>, FiltersAndHandlers<'a, ChosenInlineResult, E>,
callback_query_handlers: FiltersAndHandlers<'a, CallbackQuery, E>,
error_policy: Ep, error_policy: Ep,
} }
@ -104,7 +125,7 @@ where
H: Handler<'a, Message, E> + 'a, H: Handler<'a, Message, E> + 'a,
{ {
self.message_handlers self.message_handlers
.push((Box::new(filter), Box::new(handler))); .push(FilterAndHandler::new(filter, handler));
self self
} }
@ -114,7 +135,7 @@ where
H: Handler<'a, Message, E> + 'a, H: Handler<'a, Message, E> + 'a,
{ {
self.edited_message_handlers self.edited_message_handlers
.push((Box::new(filter), Box::new(handler))); .push(FilterAndHandler::new(filter, handler));
self self
} }
@ -124,7 +145,7 @@ where
H: Handler<'a, Message, E> + 'a, H: Handler<'a, Message, E> + 'a,
{ {
self.channel_post_handlers self.channel_post_handlers
.push((Box::new(filter), Box::new(handler))); .push(FilterAndHandler::new(filter, handler));
self self
} }
@ -138,7 +159,7 @@ where
H: Handler<'a, Message, E> + 'a, H: Handler<'a, Message, E> + 'a,
{ {
self.edited_channel_post_handlers self.edited_channel_post_handlers
.push((Box::new(filter), Box::new(handler))); .push(FilterAndHandler::new(filter, handler));
self self
} }
@ -148,7 +169,7 @@ where
H: Handler<'a, (), E> + 'a, H: Handler<'a, (), E> + 'a,
{ {
self.inline_query_handlers self.inline_query_handlers
.push((Box::new(filter), Box::new(handler))); .push(FilterAndHandler::new(filter, handler));
self self
} }
@ -162,7 +183,7 @@ where
H: Handler<'a, ChosenInlineResult, E> + 'a, H: Handler<'a, ChosenInlineResult, E> + 'a,
{ {
self.chosen_inline_result_handlers self.chosen_inline_result_handlers
.push((Box::new(filter), Box::new(handler))); .push(FilterAndHandler::new(filter, handler));
self self
} }
@ -172,7 +193,7 @@ where
H: Handler<'a, CallbackQuery, E> + 'a, H: Handler<'a, CallbackQuery, E> + 'a,
{ {
self.callback_query_handlers self.callback_query_handlers
.push((Box::new(filter), Box::new(handler))); .push(FilterAndHandler::new(filter, handler));
self self
} }
@ -238,29 +259,24 @@ where
.await; .await;
} }
async fn handle<T>(&self, update: T, handlers: &Handlers<'a, T, E>) async fn handle<T>(
where &self,
update: T,
handlers: &FiltersAndHandlers<'a, T, E>,
) where
T: std::fmt::Debug, T: std::fmt::Debug,
{ {
let handler = handlers.iter().find_map(|e| { for x in handlers {
let (filter, handler) = e; if x.filter.test(&update) {
if filter.test(&update) { if let Err(err) = x.handler.handle(update).await {
Some(handler)
} else {
None
}
});
match handler {
Some(handler) => {
if let Err(err) = handler.handle(update).await {
self.error_policy.handle_error(err).await self.error_policy.handle_error(err).await
} }
}
None => { return;
log::warn!("unhandled update {:?}", update);
} }
} }
log::warn!("unhandled update {:?}", update);
} }
} }
@ -287,8 +303,7 @@ mod tests {
use crate::{ use crate::{
dispatching::{ dispatching::{
dispatchers::filter::FilterDispatcher, dispatchers::filter::FilterDispatcher, updater::StreamUpdater,
updater::StreamUpdater,
}, },
types::{ types::{
Chat, ChatKind, ForwardKind, MediaKind, Message, MessageKind, Chat, ChatKind, ForwardKind, MediaKind, Message, MessageKind,
@ -301,7 +316,7 @@ mod tests {
let counter = &AtomicI32::new(0); let counter = &AtomicI32::new(0);
let counter2 = &AtomicI32::new(0); let counter2 = &AtomicI32::new(0);
let mut dp = FilterDispatcher::<Infallible, _>::new(|_| async { () } ) let mut dp = FilterDispatcher::<Infallible, _>::new(|_| async { () })
.message_handler(true, |_mes: Message| { .message_handler(true, |_mes: Message| {
async move { async move {
counter.fetch_add(1, Ordering::SeqCst); counter.fetch_add(1, Ordering::SeqCst);

View file

@ -1,13 +1,10 @@
use std::{ use std::{borrow::Cow, path::PathBuf};
path::PathBuf,
borrow::Cow,
};
use reqwest::multipart::Form; use reqwest::multipart::Form;
use crate::{ use crate::{
requests::utils::file_to_part, requests::utils::file_to_part,
types::{ChatId, InputMedia, ParseMode, InputFile}, types::{ChatId, InputFile, InputMedia, ParseMode},
}; };
/// This is a convenient struct that builds `reqwest::multipart::Form` /// This is a convenient struct that builds `reqwest::multipart::Form`
@ -40,7 +37,7 @@ impl FormBuilder {
// used in SendMediaGroup // used in SendMediaGroup
pub fn add_file<'a, N>(self, name: N, path_to_file: PathBuf) -> Self pub fn add_file<'a, N>(self, name: N, path_to_file: PathBuf) -> Self
where where
N: Into<Cow<'a, str>> N: Into<Cow<'a, str>>,
{ {
Self { Self {
form: self form: self