#[allow(unused)]
use crate::prelude::*;
#[allow(unused)]
use anyhow::Result;
#[derive(Debug, Clone)]
pub struct SweetError {
pub message: String,
#[cfg(not(target_arch = "wasm32"))]
assertion_depth: usize,
#[cfg(not(target_arch = "wasm32"))]
backtrace: backtrace::Backtrace,
}
impl std::error::Error for SweetError {}
impl SweetError {
pub const BACKTRACE_LEVEL_5: usize = 5;
pub const BACKTRACE_LEVEL_4: usize = 4;
pub const BACKTRACE_LEVEL_3: usize = 3;
pub const BACKTRACE_LEVEL_2: usize = 2;
pub const BACKTRACE_LEVEL_1: usize = 1;
pub const BACKTRACE_LEVEL_0: usize = 0;
#[allow(unused)]
pub fn new(message: impl Into<String>, mut assertion_depth: usize) -> Self {
assertion_depth += 2;
#[cfg(target_os = "windows")]
{
assertion_depth += 4;
}
#[cfg(target_arch = "wasm32")]
return Self {
message: message.into(),
};
#[cfg(not(target_arch = "wasm32"))]
return Self {
message: message.into(),
backtrace: backtrace::Backtrace::new_unresolved(),
assertion_depth,
};
}
pub fn panic(message: impl Into<String>) -> ! {
let backtrace_level = 5;
std::panic::panic_any(Self::new(message, backtrace_level));
}
}
impl std::fmt::Display for SweetError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.write_str(&self.message)
}
}
#[cfg(not(target_arch = "wasm32"))]
impl SweetError {
fn assertion_location(&self) -> Result<BacktraceLocation> {
let mut assertion_depth = self.assertion_depth;
loop {
if let Some(frame) = self.backtrace.frames().get(assertion_depth) {
let loc = BacktraceLocation::from_unresolved_frame(frame)?;
if !loc
.cwd_path
.to_string_lossy()
.contains(".cargo/registry/src/index.crates.io-")
{
break Ok(loc);
}
assertion_depth += 1;
} else {
anyhow::bail!(
"Failed to find backtrace frame at depth {}",
assertion_depth
);
}
}
}
pub fn backtrace_str(&self) -> Result<String> {
self.assertion_location()?.file_context()
}
}
#[cfg(test)]
mod test {
use crate::prelude::*;
#[test]
#[cfg(not(target_arch = "wasm32"))]
fn works() {
let err = SweetError::new("expected bar", 1);
let msg = err.backtrace_str().unwrap();
let lines = msg.lines().collect::<Vec<_>>();
lines[BacktraceLocation::LINE_CONTEXT_SIZE]
.xpect_contains("let err = SweetError::new");
}
#[test]
#[ignore = "use for visual testing"]
fn panics() { std::panic::panic_any(SweetError::new("expected bar", 1)); }
}