en/src/dev.rs

93 lines
2.6 KiB
Rust

pub fn elog(function: &str, message: &str) {
eprintln!("{:?} [{function}] {message}", crate::ONSET.elapsed());
}
#[macro_export]
macro_rules! log {
($fmt:expr $(, $($arg:tt)+ )? ) => {{
let mut display_path = String::new();
let mut path = std::any::type_name_of_val(&|| {})
.to_string().replace("::{{closure}}", "");
let level: u8 = std::env::var("DEBUG")
.unwrap_or("0".to_string()).trim().parse().unwrap_or(0);
if path.matches("::").count() > 3 {
if let Some(s) = path.split(" as ").next()
.map(|parent| parent.replace(['<', '>'], ""))
.and_then(|parent| { path.split(" as ").nth(1)
.and_then(|s| s.split("::").last())
.map(|caller| format!("{parent}::{caller}"))
}) { path = s; }
let path_vec: Vec<&str> = path.split("::").collect();
if let (
Some(last),
Some(second_to_last),
Some(third_to_last),
) = (
path_vec.get(path_vec.len().saturating_sub(1)),
path_vec.get(path_vec.len().saturating_sub(2)),
path_vec.get(path_vec.len().saturating_sub(3)),
) {
display_path = if level > 3 {
path.clone()
} else if level > 0 {
format!("{third_to_last}::{second_to_last}::{last}")
} else {
format!("{second_to_last}::{last}")
};
}
} else {
display_path = path.clone()
};
let filter = std::env::var("DEBUG_FILTER").unwrap_or("any".to_string());
if filter == "any" || filter.is_empty() || path.contains(&filter) {
$crate::dev::elog(&display_path, &format!($fmt $(, $($arg)+ )?));
};
}};
}
#[cfg(test)]
mod tests {
fn run_in_debug_level(level: &str) {
#[allow(unsafe_code)]
unsafe {
std::env::set_var("DEBUG", level);
log!("Debug is set to {level}");
}
}
#[test]
fn debug_var_set() {
for level in 0..9 {
run_in_debug_level(&level.to_string());
}
run_in_debug_level("");
run_in_debug_level("駄目!");
}
#[test]
fn trait_stripping() {
pub trait Loggable {
fn test(&self);
}
struct Logger {}
impl Loggable for Logger {
fn test(&self) {
log!("This is inside a trait implementation");
}
}
let logger = Logger {};
logger.test();
}
}