use core::mem;
use core::marker;
use crate::printer::Printer;
pub struct Logger<P: Printer + marker::Send + marker::Sync> {
pub inner: P,
pub level: log::LevelFilter,
}
impl<P: Printer + marker::Send + marker::Sync> log::Log for Logger<P> {
fn enabled(&self, metadata: &log::Metadata) -> bool {
metadata.level() <= self.level
}
fn log(&self, record: &log::Record) {
if self.enabled(record.metadata()) {
let inner = &self.inner as *const P as *mut P;
let inner = unsafe { &mut *inner };
inner.print(format_args!("{:<5} {}:{} - {}\n", record.level(), record.file().unwrap_or("UNKNOWN"), record.line().unwrap_or(0), record.args()))
}
}
fn flush(&self) {
}
}
pub fn init<P: Printer + marker::Send + marker::Sync>(logger: &'static Logger<P>) -> Result<(), log::SetLoggerError> {
log::set_max_level(logger.level);
#[cfg(feature = "atomic_cas")]
{
log::set_logger(logger)
}
#[cfg(not(feature = "atomic_cas"))]
{
use core::sync::atomic::{Ordering, AtomicBool};
static INIT: AtomicBool = AtomicBool::new(false);
let is_init = INIT.load(Ordering::Acquire);
INIT.store(true, Ordering::Release);
match is_init {
true => Ok(()),
false => {
unsafe {
log::set_logger_racy(logger)
}
}
}
}
}
#[inline]
pub unsafe fn trick_init<P: Printer + marker::Send + marker::Sync + 'static>(logger: &Logger<P>) -> Result<(), log::SetLoggerError> {
let logger: &'static Logger<P> = mem::transmute(logger);
init(logger)
}