use alloc::sync::Arc;
#[cfg(feature = "std")]
use core::time::Duration;
use crate::error::Error;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Action {
Continue,
Stop,
Reraise,
}
pub trait Handler: Send + Sync + core::fmt::Debug {
fn handle(&self, error: &Error) -> Action;
}
pub type HandlerRef = Arc<dyn Handler>;
macro_rules! simple_handler {
($name:ident, $ctor:ident, $action:expr, $warn:expr, $doc:expr) => {
#[doc = $doc]
#[derive(Debug, Clone, Copy, Default)]
pub struct $name;
impl Handler for $name {
fn handle(&self, error: &Error) -> Action {
if $warn {
log::warn!("{error}");
#[cfg(feature = "std")]
std::thread::sleep(Duration::from_millis(500));
}
$action
}
}
#[doc = $doc]
pub fn $ctor() -> HandlerRef {
Arc::new($name)
}
};
}
simple_handler!(
ReraiseException,
reraise_exception,
Action::Reraise,
false,
"Forward the error to the consumer of the pipeline."
);
simple_handler!(
IgnoreAndContinue,
ignore_and_continue,
Action::Continue,
false,
"Silently drop the offending item and continue."
);
simple_handler!(
WarnAndContinue,
warn_and_continue,
Action::Continue,
true,
"Log the error, drop the offending item, and continue."
);
simple_handler!(IgnoreAndStop, ignore_and_stop, Action::Stop, false, "Silently end the stream.");
simple_handler!(WarnAndStop, warn_and_stop, Action::Stop, true, "Log the error and end the stream.");
pub struct FnHandler<F>(pub F);
impl<F> core::fmt::Debug for FnHandler<F> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.write_str("FnHandler")
}
}
impl<F> Handler for FnHandler<F>
where
F: Fn(&Error) -> Action + Send + Sync,
{
fn handle(&self, error: &Error) -> Action {
(self.0)(error)
}
}
pub fn handler_fn<F>(f: F) -> HandlerRef
where
F: Fn(&Error) -> Action + Send + Sync + 'static,
{
Arc::new(FnHandler(f))
}
pub fn dispatch(handler: &dyn Handler, error: Error) -> Dispatch {
match handler.handle(&error) {
Action::Continue => Dispatch::Skip,
Action::Stop => Dispatch::Stop,
Action::Reraise => Dispatch::Yield(error),
}
}
#[derive(Debug)]
pub enum Dispatch {
Skip,
Stop,
Yield(Error),
}