use crate::valgrind;
use colored::Colorize as _;
pub fn display_errors(errors: &[valgrind::xml::Error]) {
for error in errors {
if error.kind.is_leak() {
display_leak(error);
} else {
display_generic_error(error);
}
}
let total: usize = errors.iter().map(|error| error.resources.bytes).sum();
eprintln!(
"{:>12} Leaked {} total ({} other errors)",
"Summary".red().bold(),
bytesize::ByteSize::b(total as _),
errors.iter().filter(|e| !e.kind.is_leak()).count()
);
}
fn display_leak(error: &valgrind::xml::Error) {
eprintln!(
"{:>12} leaked {} in {} block{}",
"Error".red().bold(),
bytesize::ByteSize::b(error.resources.bytes as _),
error.resources.blocks,
if error.resources.blocks == 1 { "" } else { "s" }
);
let stack = &error.stack_trace[0]; display_stack_trace("stack trace (user code at the bottom)", stack);
}
fn display_generic_error(error: &valgrind::xml::Error) {
eprintln!(
"{:>12} {}",
"Error".red().bold(),
error.main_info.as_ref().map_or("unknown", String::as_str)
);
let stack = &error.stack_trace[0]; display_stack_trace("main stack trace (user code at the bottom)", stack);
error
.stack_trace
.iter()
.skip(1)
.enumerate()
.map(|(index, stack)| (error.auxiliary_info.get(index), stack))
.for_each(|(msg, stack)| {
display_stack_trace(
msg.map_or_else(|| "additional stack trace", String::as_str),
stack,
);
});
}
fn display_stack_trace(msg: &str, stack: &valgrind::xml::Stack) {
eprintln!("{:>12} {}", "Info".cyan().bold(), msg);
stack
.frames
.iter()
.for_each(|frame| eprintln!(" at {frame}"));
}
pub fn display_stack_overflow(output: &str) {
let error = "Error".red().bold();
let info = "Info".cyan().bold();
eprintln!("{error:>12}: looks like the program overflowed its stack");
eprintln!("{info:>12}: valgrind says:");
output
.lines()
.for_each(|line| eprintln!(" {line}"));
}