use cfg_if::cfg_if;
use crate::{
formatter::{Formatter, FullFormatter},
prelude::*,
sync::*,
Error, ErrorHandler,
};
pub(crate) type SinkErrorHandler = Atomic<Option<ErrorHandler>>;
cfg_if! {
if #[cfg(test)] {
use static_assertions::const_assert;
const_assert!(Atomic::<SinkErrorHandler>::is_lock_free());
}
}
pub(crate) const SINK_DEFAULT_LEVEL_FILTER: LevelFilter = LevelFilter::All;
pub(crate) struct CommonImpl {
pub(crate) level_filter: Atomic<LevelFilter>,
pub(crate) formatter: SpinRwLock<Box<dyn Formatter>>,
pub(crate) error_handler: SinkErrorHandler,
}
impl CommonImpl {
#[must_use]
pub(crate) fn from_builder(common_builder_impl: CommonBuilderImpl) -> Self {
Self::from_builder_with_formatter(common_builder_impl, || Box::new(FullFormatter::new()))
}
#[must_use]
pub(crate) fn from_builder_with_formatter(
common_builder_impl: CommonBuilderImpl,
fallback: impl FnOnce() -> Box<dyn Formatter>,
) -> Self {
Self {
level_filter: Atomic::new(common_builder_impl.level_filter),
formatter: SpinRwLock::new(common_builder_impl.formatter.unwrap_or_else(fallback)),
error_handler: Atomic::new(common_builder_impl.error_handler),
}
}
#[allow(dead_code)]
#[must_use]
pub(crate) fn with_formatter(formatter: Box<dyn Formatter>) -> Self {
Self {
level_filter: Atomic::new(LevelFilter::All),
formatter: SpinRwLock::new(formatter),
error_handler: Atomic::new(None),
}
}
pub(crate) fn non_returnable_error(&self, from: impl AsRef<str>, err: Error) {
match self.error_handler.load(Ordering::Relaxed) {
Some(handler) => handler(err),
None => crate::default_error_handler(from, err),
}
}
}
pub(crate) struct CommonBuilderImpl {
pub(crate) level_filter: LevelFilter,
pub(crate) formatter: Option<Box<dyn Formatter>>,
pub(crate) error_handler: Option<ErrorHandler>,
}
impl CommonBuilderImpl {
#[must_use]
pub(crate) fn new() -> Self {
Self {
level_filter: SINK_DEFAULT_LEVEL_FILTER,
formatter: None,
error_handler: None,
}
}
}
macro_rules! common_impl {
( @Sink: $($field:ident).+ ) => {
$crate::sink::helper::common_impl!(@SinkCustom {
level_filter: $($field).+.level_filter,
formatter: $($field).+.formatter,
error_handler: $($field).+.error_handler,
});
};
( @SinkCustom {
level_filter: $($level_filter:ident).+,
formatter: $($formatter:ident).+,
error_handler: $($error_handler:ident).+$(,)?
} ) => {
$crate::sink::helper::common_impl!(@SinkCustomInner@level_filter: $($level_filter).+);
$crate::sink::helper::common_impl!(@SinkCustomInner@formatter: $($formatter).+);
$crate::sink::helper::common_impl!(@SinkCustomInner@error_handler: $($error_handler).+);
};
( @SinkCustomInner@level_filter: None ) => {};
( @SinkCustomInner@level_filter: $($field:ident).+ ) => {
fn level_filter(&self) -> $crate::LevelFilter {
self.$($field).+.load($crate::sync::Ordering::Relaxed)
}
fn set_level_filter(&self, level_filter: $crate::LevelFilter) {
self.$($field).+.store(level_filter, $crate::sync::Ordering::Relaxed);
}
};
( @SinkCustomInner@formatter: None ) => {};
( @SinkCustomInner@formatter: $($field:ident).+ ) => {
fn set_formatter(&self, formatter: Box<dyn $crate::formatter::Formatter>) {
*self.$($field).+.write() = formatter;
}
};
( @SinkCustomInner@error_handler: None ) => {};
( @SinkCustomInner@error_handler: $($field:ident).+ ) => {
fn set_error_handler(&self, handler: Option<$crate::ErrorHandler>) {
self.$($field).+.store(handler, $crate::sync::Ordering::Relaxed);
}
};
( @SinkBuilder: $($field:ident).+ ) => {
$crate::sink::helper::common_impl!(@SinkBuilderCustomInner@level_filter: $($field).+.level_filter);
$crate::sink::helper::common_impl!(@SinkBuilderCustomInner@formatter: $($field).+.formatter);
$crate::sink::helper::common_impl!(@SinkBuilderCustomInner@error_handler: $($field).+.error_handler);
};
( @SinkBuilderCustom {
level_filter: $($level_filter:ident).+,
formatter: $($formatter:ident).+,
error_handler: $($error_handler:ident).+$(,)?
} ) => {
$crate::sink::helper::common_impl!(@SinkBuilderCustomInner@level_filter: $($level_filter).+);
$crate::sink::helper::common_impl!(@SinkBuilderCustomInner@formatter: $($formatter).+);
$crate::sink::helper::common_impl!(@SinkBuilderCustomInner@error_handler: $($error_handler).+);
};
( @SinkBuilderCustomInner@level_filter: None ) => {};
( @SinkBuilderCustomInner@level_filter: $($field:ident).+ ) => {
$crate::sink::helper::common_impl! {
@SinkBuilderCustomInner@level_filter: $($field).+
}
};
( $(#[$attr:meta])* @SinkBuilderCustomInner@level_filter: $($field:ident).+ ) => {
$(#[$attr])*
#[must_use]
pub fn level_filter(mut self, level_filter: $crate::LevelFilter) -> Self {
self.$($field).+ = level_filter;
self
}
};
( @SinkBuilderCustomInner@formatter: None ) => {};
( @SinkBuilderCustomInner@formatter: $($field:ident).+ ) => {
$crate::sink::helper::common_impl! {
@SinkBuilderCustomInner@formatter: $($field).+
}
};
( $(#[$attr:meta])* @SinkBuilderCustomInner@formatter: $($field:ident).+ ) => {
$(#[$attr])*
#[must_use]
pub fn formatter(mut self, formatter: Box<dyn $crate::formatter::Formatter>) -> Self {
self.$($field).+ = Some(formatter);
self
}
};
( @SinkBuilderCustomInner@error_handler: None ) => {};
( @SinkBuilderCustomInner@error_handler: $($field:ident).+ ) => {
$crate::sink::helper::common_impl! {
@SinkBuilderCustomInner@error_handler: $($field).+
}
};
( $(#[$attr:meta])* @SinkBuilderCustomInner@error_handler: $($field:ident).+ ) => {
$(#[$attr])*
#[must_use]
pub fn error_handler(mut self, handler: $crate::ErrorHandler) -> Self {
self.$($field).+ = Some(handler);
self
}
};
}
pub(crate) use common_impl;