use core::{fmt, panic};
use std::path::{Path, PathBuf};
#[derive(Clone, Debug)]
pub struct Location {
location: &'static panic::Location<'static>,
name: String,
}
impl Location {
#[track_caller]
pub fn new<N: core::fmt::Display>(name: N) -> Self {
let location = panic::Location::caller();
let name = name.to_string();
Self { location, name }
}
#[track_caller]
#[allow(clippy::manual_map)] pub fn from_thread_name() -> Option<Self> {
let thread = std::thread::current();
if let Some(name) = thread.name().filter(|name| *name != "main") {
let name = name
.split("::")
.chain(Some("events"))
.collect::<Vec<_>>()
.join("__");
Some(Self::new(name))
} else {
None
}
}
pub fn snapshot_log(&self, output: &[String]) {
if cfg!(miri) {
return;
}
let value = output.join("\n");
let name = self.name.as_str();
let mut settings = insta::Settings::clone_current();
settings.set_prepend_module_to_snapshot(false);
settings.set_input_file(self.location.file());
settings.set_snapshot_path(self.snapshot_path());
settings.set_omit_expression(true);
settings.bind(|| {
insta::assert_snapshot!(name, &value);
});
}
fn snapshot_path(&self) -> PathBuf {
let ws = Path::new(concat!(env!("CARGO_MANIFEST_DIR"), "/../.."));
let file = Path::new(self.location.file());
let file = if file.is_relative() {
ws.join(file)
} else {
file.to_path_buf()
};
file.canonicalize()
.unwrap()
.parent()
.unwrap()
.join("snapshots")
}
}
pub trait Fmt {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result;
fn to_snapshot(&self) -> ToSnapshot<'_, Self> {
ToSnapshot(self)
}
}
pub struct ToSnapshot<'a, T: ?Sized>(&'a T);
impl<T: Fmt + ?Sized> fmt::Debug for ToSnapshot<'_, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}