use std::cell::RefCell;
use std::fmt::{self, Write};
thread_local! {
pub static STACK: RefCell<String> = RefCell::new(String::new());
}
pub struct Trace(pub Vec<String>);
impl Trace {
pub fn new() -> Self {
Trace(Vec::<String>::new())
}
pub fn raise(what: &str) -> ! {
panic!("{}", what);
}
pub fn stack() -> String {
STACK.with(|stack| stack.borrow().clone())
}
pub fn path_sanitize(str: String) -> String {
str.trim().to_string()
}
pub fn stack_push(func: &str, args: &[String]) {
STACK.with(|stack| {
let mut stack = stack.borrow_mut();
let func_name = func;
writeln!(stack, " {}", func_name).unwrap();
let arga = extract_paths(&args[0]);
for arg in arga {
writeln!(stack, " {}", arg).unwrap();
}
});
}
}
impl Drop for Trace
where
{
fn drop(&mut self) {
STACK.take().replace_range(0..Self::stack().len(), "");
self.0.pop().take();
}
}
pub fn fix_func(func: &str) -> &str {
func.split('(').next().unwrap_or(func)
}
impl fmt::Display for Trace{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", Self::path_sanitize(self.0[0].to_string()))
}
}
pub fn extract_paths(input: &str) -> Vec<String> {
let mut paths = Vec::new();
for part in input.split('(') {
if let Some(end) = part.find(')') {
let content = &part[..end];
let trimmed = content.trim_matches(|c| c == '"' || c == ' ');
if !trimmed.is_empty() {
paths.push(trimmed.to_string());
}
}
}
paths
}