yoshi-derive

Crates.ioyoshi-derive
lib.rsyoshi-derive
version0.1.5
created_at2025-06-01 19:17:21.772095+00
updated_at2025-06-04 07:25:16.848661+00
descriptionProcedural-macro helpers for deriving Yoshi errors.
homepage
repositoryhttps://github.com/arcmoonstudios/yoshi
max_upload_size
id1697433
size140,242
Lord Xyn (arcmoonstudios)

documentation

README

yoshi-derive

Yoshi Logo

Crates.io Docs.rs Rust Version License: MIT OR Apache-2.0

Derive macros for automatically generating Yoshi error types. Because writing error boilerplate is boring.

What's this?

Generates std::error::Error implementations, Display, and conversion to Yoshi types automatically.

Installation

[dependencies]
yoshi-derive = "0.1"
yoshi = "0.1"

Basic Usage

use yoshi_derive::YoshiError;

#[derive(Debug, YoshiError)]
pub enum MyError {
    #[yoshi(display = "User {user_id} not found")]
    #[yoshi(kind = "NotFound")]
    UserNotFound { user_id: u32 },

    #[yoshi(display = "Failed to parse config: {source}")]
    ParseError {
        #[yoshi(source)]
        source: std::io::Error,
        #[yoshi(context = "config_file")]
        path: String,
    },
}

Attributes

Container Attributes (#[yoshi(...)] on enums)

Attribute Description Example
error_code_prefix Prefix for error codes #[yoshi(error_code_prefix = "HTTP")]
default_severity Default severity (0-255) #[yoshi(default_severity = 75)]

Variant Attributes (#[yoshi(...)] on enum variants)

Attribute Description Example
display Custom display format #[yoshi(display = "Error: {message}")]
kind Map to YoshiKind #[yoshi(kind = "Network")]
error_code Unique error code #[yoshi(error_code = 1001)]
severity Severity level #[yoshi(severity = 80)]
transient Mark as retryable #[yoshi(transient = true)]
suggestion Recovery suggestion #[yoshi(suggestion = "Check network")]

Field Attributes (#[yoshi(...)] on struct fields)

Attribute Description Example
source Mark as error source #[yoshi(source)]
context Add to context metadata #[yoshi(context = "file_path")]
shell Add as typed shell #[yoshi(shell)]
skip Skip in Display #[yoshi(skip)]

Advanced Example

use yoshi_derive::YoshiError;

#[derive(Debug, YoshiError)]
#[yoshi(error_code_prefix = "DB")]
#[yoshi(default_severity = 75)]
pub enum DatabaseError {
    #[yoshi(error_code = 1001)]
    #[yoshi(display = "Connection to {host}:{port} failed")]
    #[yoshi(kind = "Network")]
    #[yoshi(severity = 120)]
    #[yoshi(transient = true)]
    ConnectionFailed {
        host: String,
        port: u16,
        #[yoshi(source)]
        cause: std::io::Error,
        #[yoshi(context = "connection_timeout")]
        timeout: std::time::Duration,
    },

    #[yoshi(error_code = 2001)]
    #[yoshi(display = "Query failed: {query}")]
    #[yoshi(kind = "Internal")]
    QueryFailed {
        query: String,
        #[yoshi(shell)]
        execution_stats: QueryStats,
    },
}

#[derive(Debug)]
struct QueryStats {
    duration_ms: u64,
    rows_affected: usize,
}

Generated Code

The derive macro automatically creates:

  • std::fmt::Display implementation
  • std::error::Error implementation
  • From<YourError> for yoshi_std::Yoshi conversion
  • Error code and severity methods

Smart Inference

The macro automatically infers attributes based on naming:

  • timeout, expiredkind = "Timeout"
  • network, connectionkind = "Network"
  • not_found, missingkind = "NotFound"
  • std::io::Error fields → source = true

Performance

  • Compilation: <100ms for typical enums (<50 variants)
  • Runtime: Zero overhead - generates efficient code
  • Memory: Uses static strings where possible

License

Licensed under either of Apache License, Version 2.0 or MIT License at your option.

Commit count: 64

cargo fmt