use alloc::borrow::Cow;
use core::fmt;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct PassError {
pass: &'static str,
message: Cow<'static, str>,
}
impl PassError {
#[must_use]
pub fn new(message: impl Into<Cow<'static, str>>) -> Self {
Self {
pass: "",
message: message.into(),
}
}
#[must_use]
pub fn pass(&self) -> &str {
self.pass
}
#[must_use]
pub fn message(&self) -> &str {
&self.message
}
pub(crate) fn in_pass(mut self, name: &'static str) -> Self {
self.pass = name;
self
}
}
impl fmt::Display for PassError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.pass.is_empty() {
write!(f, "pass failed: {}", self.message)
} else {
write!(f, "pass `{}` failed: {}", self.pass, self.message)
}
}
}
impl core::error::Error for PassError {}
#[cfg(test)]
#[allow(clippy::expect_used, clippy::unwrap_used)]
mod tests {
use super::*;
use alloc::string::{String, ToString};
#[test]
fn test_new_accepts_literal_and_owned() {
assert_eq!(PassError::new("x"), PassError::new(String::from("x")));
}
#[test]
fn test_message_is_preserved() {
assert_eq!(
PassError::new("division by zero").message(),
"division by zero"
);
}
#[test]
fn test_pass_is_empty_before_stamping() {
assert_eq!(PassError::new("boom").pass(), "");
}
#[test]
fn test_in_pass_stamps_name() {
let err = PassError::new("boom").in_pass("const-fold");
assert_eq!(err.pass(), "const-fold");
assert_eq!(err.message(), "boom");
}
#[test]
fn test_display_without_pass_name() {
assert_eq!(PassError::new("boom").to_string(), "pass failed: boom");
}
#[test]
fn test_display_with_pass_name() {
let err = PassError::new("boom").in_pass("simplify");
assert_eq!(err.to_string(), "pass `simplify` failed: boom");
}
#[test]
fn test_error_trait_is_implemented() {
fn assert_error<E: core::error::Error>(_: &E) {}
assert_error(&PassError::new("boom"));
}
}