diff --git a/Cargo.toml b/Cargo.toml index 6b662740..b74a1f87 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,4 +21,5 @@ thiserror = "1.0.2" [features] default = [] -unstable-stream = [] # add streams to public API \ No newline at end of file +unstable-stream = [] # add streams to public API +never-type = [] # add never type (`!`) to punlic API diff --git a/src/dispatching/dispatchers/filter/error_policy.rs b/src/dispatching/dispatchers/filter/error_policy.rs index 91bd322b..f69ef4e8 100644 --- a/src/dispatching/dispatchers/filter/error_policy.rs +++ b/src/dispatching/dispatchers/filter/error_policy.rs @@ -1,7 +1,10 @@ -use std::future::Future; +use std::{ + pin::Pin, + future::Future, + convert::Infallible, +}; use async_trait::async_trait; -use std::pin::Pin; /// Implementors of this trait are treated as error-handlers. #[async_trait] @@ -11,6 +14,113 @@ pub trait ErrorPolicy { E: 'async_trait; } +/// Error policy that silently ignores all errors +/// +/// ## Example +/// ``` +/// # #[tokio::main] +/// # async fn main() { +/// use telebofr::dispatching::dispatchers::filter::error_policy::{ +/// ErrorPolicy, +/// Ignore, +/// }; +/// +/// Ignore.handle_error(()).await; +/// Ignore.handle_error(404).await; +/// Ignore.handle_error(String::from("error")).await; +/// # } +/// ``` +pub struct Ignore; + +#[async_trait] +impl ErrorPolicy for Ignore +where + E: Send, +{ + async fn handle_error(&self, _: E) + where + E: 'async_trait + {} +} + +/// Error policy that silently ignores all errors that can never happen (e.g.: [`!`] or [`Infallible`]) +/// +/// ## Examples +/// ``` +/// # #[tokio::main] +/// # async fn main() { +/// use std::convert::{TryInto, Infallible}; +/// +/// use telebofr::dispatching::dispatchers::filter::error_policy::{ +/// ErrorPolicy, +/// IgnoreSafe, +/// }; +/// +/// let result: Result = "str".try_into(); +/// match result { +/// Ok(string) => println!("{}", string), +/// Err(inf) => IgnoreSafe.handle_error(inf).await, +/// } +/// +/// IgnoreSafe.handle_error(return).await; // return type of `return` is `!` (aka never) +/// # } +/// ``` +/// +/// ```compile_fail +/// use telebofr::dispatching::dispatchers::filter::error_policy::{ +/// ErrorPolicy, +/// IgnoreSafe, +/// }; +/// +/// IgnoreSafe.handle_error(0); +/// ``` +/// +/// ## Note +/// Never type is not stabilized yet (see [`#35121`]) so all API that uses [`!`] +/// (including `impl ErrorPolicy for IgnoreSafe`) we hide under the +/// `never-type` cargo feature. +/// +/// [`!`]: https://doc.rust-lang.org/std/primitive.never.html +/// [`Infallible`]: std::convert::Infallible +/// [`#35121`]: https://github.com/rust-lang/rust/issues/35121 +pub struct IgnoreSafe; + +#[cfg(feature = "never-type")] +#[async_trait] +impl ErrorPolicy for IgnoreSafe { + async fn handle_error(&self, never: !) + where + !: 'async_trait + { + never + } +} + +#[async_trait] +impl ErrorPolicy for IgnoreSafe { + async fn handle_error(&self, inf: Infallible) + where + Infallible: 'async_trait + { + match inf {} + } +} + +/// Implementation of `ErrorPolicy` for `async fn`s +/// +/// ## Example +/// ``` +/// # #[tokio::main] +/// # async fn main() { +/// use telebofr::dispatching::dispatchers::filter::error_policy::ErrorPolicy; +/// +/// let closure = |e: i32| async move { +/// eprintln!("Error code{}", e) +/// }; +/// +/// closure.handle_error(404).await; +/// # } +/// ``` impl ErrorPolicy for F where F: Fn(E) -> Fut + Sync, diff --git a/src/lib.rs b/src/lib.rs index 838a211a..339931e3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,5 @@ +#![cfg_attr(feature = "never-type", feature(never_type))] + #[macro_use] extern crate derive_more; #[macro_use]