use core::sync::atomic::{AtomicBool, Ordering};
pub use log::{self, LevelFilter as Level};
use log::{Log, Metadata, Record};
pub struct Logger {
max_level: Level,
}
impl Logger {
pub const fn with_max_level(max_level: Level) -> Self {
Self { max_level }
}
pub fn init(&'static self) {
log::set_max_level(self.max_level);
log::set_logger(self).unwrap();
}
}
impl Log for Logger {
fn enabled(&self, metadata: &Metadata) -> bool {
metadata.level() <= self.max_level
}
fn log(&self, record: &Record) {
if self.enabled(record.metadata()) {
use log::Level;
let message = alloc::format!("{}", record.args());
let level = match record.level() {
Level::Error => 1,
Level::Warn => 2,
Level::Info => 3,
Level::Debug => 4,
Level::Trace => 5,
};
let _ = crate::ext().log(level, &message);
}
}
fn flush(&self) {}
}
pub fn once(x: fn()) {
static INIT_LOCK: AtomicBool = AtomicBool::new(false);
if !INIT_LOCK.swap(true, Ordering::Relaxed) {
x();
}
}
#[macro_export]
macro_rules! register_logger {
($logger: expr) => {
#[no_mangle]
fn pink_logger_try_init() {
$crate::logger::once(|| $logger.init());
}
};
}
#[macro_export]
macro_rules! try_init {
() => {
extern "Rust" {
fn pink_logger_try_init();
}
unsafe { pink_logger_try_init() };
};
}
#[macro_export(local_inner_macros)]
macro_rules! error {
($($arg:tt)+) => {{ try_init!(); $crate::logger::log::error!($($arg)+) }}
}
#[macro_export(local_inner_macros)]
macro_rules! warn {
($($arg:tt)+) => {{ try_init!(); $crate::logger::log::warn!($($arg)+) }}
}
#[macro_export(local_inner_macros)]
macro_rules! info {
($($arg:tt)+) => {{ try_init!(); $crate::logger::log::info!($($arg)+) }}
}
#[macro_export(local_inner_macros)]
macro_rules! debug {
($($arg:tt)+) => {{ try_init!(); $crate::logger::log::debug!($($arg)+) }}
}
#[macro_export(local_inner_macros)]
macro_rules! trace {
($($arg:tt)+) => {{ try_init!(); $crate::logger::log::trace!($($arg)+) }}
}