use std::{collections::VecDeque, io::Write, path::Path};
pub trait Dumpable {
fn dump_to_string(&self) -> String;
#[track_caller]
fn dump(&self) {
let loc = std::panic::Location::caller();
println!("──── dumped at {}:{} ────", loc.file(), loc.line());
println!("{}", self.dump_to_string());
}
#[track_caller]
fn dump_and_wait(&self) {
let loc = std::panic::Location::caller();
println!("──── paused at {}:{} ────\n", loc.file(), loc.line());
println!("{}", self.dump_to_string());
let mut input = String::new();
print!("\n» ");
std::io::stdout().flush().unwrap();
std::io::stdin()
.read_line(&mut input)
.expect("Failed to read line");
}
#[track_caller]
fn dump_and_panic(&self) -> ! {
let loc = std::panic::Location::caller();
println!("════ ERROR at {}:{} ════\n", loc.file(), loc.line());
println!("{}", self.dump_to_string());
panic!();
}
fn dump_to_file<P: AsRef<Path>>(&self, path: P) {
std::fs::write(path, self.dump_to_string()).expect("Failed to write to file");
}
}
impl<E: Dumpable> Dumpable for [E] {
fn dump_to_string(&self) -> String {
let elements: Vec<String> = self.iter().map(|e| e.dump_to_string()).collect();
format!("[{}]", elements.join(", "))
}
}
impl Dumpable for str {
fn dump_to_string(&self) -> String {
self.to_string()
}
}
impl<E: Dumpable> Dumpable for VecDeque<E> {
fn dump_to_string(&self) -> String {
let elements: Vec<String> = self.iter().map(|e| e.dump_to_string()).collect();
format!("[{}]", elements.join(", "))
}
}
impl<A: Dumpable, B: Dumpable> Dumpable for (A, B) {
fn dump_to_string(&self) -> String {
format!("({}, {})", self.0.dump_to_string(), self.1.dump_to_string())
}
}
impl<A: Dumpable, B: Dumpable, C: Dumpable> Dumpable for (A, B, C) {
fn dump_to_string(&self) -> String {
format!(
"({}, {}, {})",
self.0.dump_to_string(),
self.1.dump_to_string(),
self.2.dump_to_string()
)
}
}
macro_rules! impl_dumpable_via_display {
($($t:ty),* $(,)?) => {
$(
impl $crate::Dumpable for $t {
fn dump_to_string(&self) -> String {
format!("{}", self)
}
}
)*
};
}
macro_rules! impl_dumpable_via_debug {
($($t:ty),* $(,)?) => {
$(
impl $crate::Dumpable for $t {
fn dump_to_string(&self) -> String {
format!("{:?}", self)
}
}
)*
};
}
impl_dumpable_via_debug!(());
impl_dumpable_via_display!(
u8,
u16,
u32,
u64,
u128,
usize,
i8,
i16,
i32,
i64,
i128,
isize,
f64,
f32,
std::backtrace::Backtrace
);