use std::sync::{Mutex, LazyLock};
use std::collections::HashMap;
#[derive(Debug, Default)]
pub(crate) struct DebugState {
pub(crate) indent: usize,
pub(crate) line: usize,
pub(crate) item_details: HashMap<(usize, &'static str, String), ItemDetails>
}
#[derive(Debug, Default)]
pub(crate) struct ItemDetails {
pub(crate) call_details: HashMap<(&'static str, Vec<String>), CallDetails>
}
#[derive(Debug, Default)]
pub(crate) struct CallDetails {
pub(crate) count: usize,
pub(crate) last_line: Option<usize>
}
pub(crate) static DEBUG_STATE: LazyLock<Mutex<DebugState>> = LazyLock::new(Default::default);
pub(crate) struct Deindenter;
impl std::ops::Drop for Deindenter {
#[allow(clippy::arithmetic_side_effects, reason = "INDENT gets decremented exactly once per increment and always after.")]
fn drop(&mut self) {
crate::util::DEBUG_STATE.lock().expect("").indent -= 1;
}
}
macro_rules! debug {
($func:pat, $self:expr $(, $arg:expr)*) => {
#[allow(clippy::arithmetic_side_effects, reason = "God help you if your config gets [`usize::MAX`] layers deep.")]
let _deindenter = {
let mut dsl = crate::util::DEBUG_STATE.lock().unwrap();
let indent = dsl.indent;
let line = dsl.line;
let call_details = dsl.item_details.entry(($self as *const _ as usize, std::any::type_name_of_val($self), format!("{:?}", $self))).or_default()
.call_details.entry((stringify!($func), vec![$(format!("{:?}", $arg)),*])).or_default();
eprintln!(
"{:>3}-{:>3}-{:>3}-{}{}",
line,
match call_details.count {
0 => "".to_string(),
x => x.to_string()
},
match call_details.last_line {
Some(x) => x.to_string(),
None => "".to_string()
},
"|---".repeat(indent),
stringify!($func)
);
eprintln!(" {}- self: {:?}", "| ".repeat(indent), $self);
$(eprintln!(" {}- {}: {:?}", "| ".repeat(indent), stringify!($arg), $arg);)*
call_details.count += 1;
call_details.last_line = Some(line);
dsl.line += 1;
dsl.indent += 1;
crate::util::Deindenter
};
}
}
pub(crate) use debug;