#![doc(test(attr(deny(warnings))))]
#![warn(missing_docs)]
#![forbid(unsafe_code)]
#![allow(clippy::redundant_allocation)]
use std::sync::Arc;
use arc_swap::ArcSwap;
use log::{Log, Metadata, Record, SetLoggerError};
use once_cell::sync::Lazy;
pub struct Dummy;
impl Log for Dummy {
fn enabled(&self, _metadata: &Metadata) -> bool {
false
}
fn log(&self, _record: &Record) {}
fn flush(&self) {}
}
pub struct Reroute {
inner: ArcSwap<Box<dyn Log>>,
}
impl Reroute {
pub fn new() -> Self {
Default::default()
}
pub fn reroute_boxed(&self, log: Box<dyn Log>) {
self.reroute_arc(Arc::new(log))
}
pub fn reroute_arc(&self, log: Arc<Box<dyn Log>>) {
let old = self.inner.swap(log);
old.flush();
}
pub fn reroute<L: Log + 'static>(&self, log: L) {
self.reroute_boxed(Box::new(log));
}
pub fn clear(&self) {
self.reroute(Dummy);
}
pub fn get(&self) -> Arc<Box<dyn Log>> {
self.inner.load_full()
}
}
impl Log for Reroute {
fn enabled(&self, metadata: &Metadata) -> bool {
self.inner.load().enabled(metadata)
}
fn log(&self, record: &Record) {
self.inner.load().log(record)
}
fn flush(&self) {
self.inner.load().flush()
}
}
impl Default for Reroute {
fn default() -> Self {
Self {
inner: ArcSwap::from(Arc::new(Box::new(Dummy) as Box<dyn Log>)),
}
}
}
pub static REROUTE: Lazy<Reroute> = Lazy::new(Reroute::default);
pub fn init() -> Result<(), SetLoggerError> {
log::set_logger(&*REROUTE)
}
pub fn reroute<L: Log + 'static>(log: L) {
REROUTE.reroute(log);
}
pub fn reroute_boxed(log: Box<dyn Log>) {
REROUTE.reroute_boxed(log)
}