use colored::Colorize;
use std::ops::Not;
#[derive(Debug, Default)]
pub struct Information {
pub(crate) messages: Vec<String>,
pub left_dbg: String,
pub(crate) explanation: Option<&'static str>,
pub(crate) from_macro: Option<FromMacro>,
}
impl Information {
pub fn new(from_macro: Option<FromMacro>, left_dbg: String) -> Self {
Information {
messages: Default::default(),
explanation: Default::default(),
left_dbg,
from_macro,
}
}
fn panic(msg: String) -> ! {
use std::panic::{set_hook, PanicInfo};
use std::sync::Once;
struct FluidPanic(String);
fn panic_message(info: &PanicInfo) {
match info.payload().downcast_ref::<FluidPanic>() {
Some(p) => print!("{}", p.0),
None => println!("{}", info),
}
}
static SET_HOOK: Once = Once::new();
SET_HOOK.call_once(|| set_hook(Box::new(panic_message)));
panic!(FluidPanic(msg))
}
}
impl Drop for Information {
fn drop(&mut self) {
if self.messages.is_empty().not() {
let header = if let Some(ref from_macro) = self.from_macro {
let case = from_macro
.case
.map(|s| format!(", for the case {}", s.bold()))
.unwrap_or_default();
format!(
"\rThe test failed at {}{}:",
from_macro.location.bold(),
case
)
.red()
} else {
"The test failed:".red()
};
let explanation = self
.explanation
.map(|s| format!("This test should pass because {}.\n", s))
.unwrap_or_default();
let message = self.messages.join("\n\n");
let msg = format!("{}\n{}\n{}", header, message, explanation);
Self::panic(msg.bright_white().to_string())
}
}
}
#[derive(Debug)]
pub struct FromMacro {
pub stringified: &'static str,
pub location: &'static str,
pub case: Option<&'static str>,
}