geez 0.1.0

geez — Global Error Embedding Zero-cost. Declarative error enums, thiserror-like attrs, zero deps
Documentation
use geez::geez;
use std::error::Error;
use std::io;

geez! {
    pub enum AppError {
        #[from]
        Io(io::Error),

        #[transparent]
        Other(OtherError),

        #[source]
        Wrapped(io::Error),

        #[error("parse failed: {0}")]
        Parse(String),

        Timeout => "request timed out",

        NotFound,
    }
}

#[derive(Debug)]
pub struct OtherError;

impl std::fmt::Display for OtherError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "other blew up")
    }
}

impl Error for OtherError {}

#[test]
fn unit_default_message() {
    assert_eq!(AppError::NotFound.to_string(), "NotFound");
}

#[test]
fn arrow_message() {
    assert_eq!(AppError::Timeout.to_string(), "request timed out");
}

#[test]
fn error_attr_message() {
    let err = AppError::Parse("nope".into());
    assert_eq!(err.to_string(), "parse failed: nope");
    assert!(err.source().is_none());
}

#[test]
fn from_io_and_question_mark() {
    fn boom() -> Result<()> {
        Err(io::Error::new(io::ErrorKind::NotFound, "missing"))?;
        Ok(())
    }

    let err = boom().unwrap_err();
    assert!(matches!(err, AppError::Io(_)));
    assert_eq!(err.source().unwrap().to_string(), "missing");
}

#[test]
fn transparent_forwards_display_and_source() {
    let err = AppError::from(OtherError);
    assert_eq!(err.to_string(), "other blew up");
    assert!(err.source().is_some());
    assert_eq!(err.source().unwrap().to_string(), "other blew up");
}

#[test]
fn source_without_from() {
    let inner = io::Error::new(io::ErrorKind::Other, "wrapped");
    let err = AppError::Wrapped(inner);
    assert_eq!(err.source().unwrap().to_string(), "wrapped");

    // #[from] on Io wins From<io::Error>; Wrapped stays manual.
    let via_from = AppError::from(io::Error::other("via from"));
    assert!(matches!(via_from, AppError::Io(_)));
}

#[test]
fn result_alias_exists() {
    let ok: Result<u8> = Ok(7);
    assert_eq!(ok.unwrap(), 7);
}