waddling-errors 0.7.3

Structured, secure-by-default diagnostic codes for distributed systems with no_std and role-based documentation
Documentation
//! Example demonstrating documented trait implementations
//!
//! This shows Level 2: Adding documentation metadata to your components
//! and primaries for better doc generation.
//!
//! Run with: cargo run --example trait_based_documented

use waddling_errors::prelude::*;
use waddling_errors::{ComponentIdDocumented, PrimaryIdDocumented};

// ============================================================================
// Component with Documentation
// ============================================================================

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
enum Component {
    Parser,
    Semantic,
}

impl ComponentId for Component {
    fn as_str(&self) -> &'static str {
        match self {
            Component::Parser => "PARSER",
            Component::Semantic => "SEMANTIC",
        }
    }
}

// Add documentation metadata
impl ComponentIdDocumented for Component {
    fn description(&self) -> Option<&'static str> {
        Some(match self {
            Component::Parser => "Syntax parsing and tokenization errors",
            Component::Semantic => "Type checking and semantic analysis errors",
        })
    }

    fn examples(&self) -> &'static [&'static str] {
        match self {
            Component::Parser => &[
                "E.PARSER.SYNTAX.001: Missing semicolon",
                "E.PARSER.SYNTAX.002: Unexpected token",
            ],
            Component::Semantic => &[
                "E.SEMANTIC.TYPE.001: Type mismatch",
                "E.SEMANTIC.TYPE.002: Undefined variable",
            ],
        }
    }

    fn tags(&self) -> &'static [&'static str] {
        match self {
            Component::Parser => &["frontend", "syntax"],
            Component::Semantic => &["frontend", "types", "analysis"],
        }
    }
}

// ============================================================================
// Primary with Documentation
// ============================================================================

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
enum Primary {
    Syntax,
    Type,
}

impl PrimaryId for Primary {
    fn as_str(&self) -> &'static str {
        match self {
            Primary::Syntax => "SYNTAX",
            Primary::Type => "TYPE",
        }
    }
}

// Add documentation metadata
impl PrimaryIdDocumented for Primary {
    fn description(&self) -> Option<&'static str> {
        Some(match self {
            Primary::Syntax => "Syntax-level parsing errors and token issues",
            Primary::Type => "Type system violations and inference failures",
        })
    }

    fn related(&self) -> &'static [&'static str] {
        match self {
            Primary::Syntax => &["PARSE", "TOKEN"],
            Primary::Type => &["INFER", "CHECK"],
        }
    }
}

// ============================================================================
// Define Error Codes
// ============================================================================

// Using sequence 3 (INVALID) for validation failures per SEQUENCE-CONVENTIONS.md
const ERR_PARSER_SYNTAX: Code<Component, Primary> =
    Code::error(Component::Parser, Primary::Syntax, 3);

const ERR_SEMANTIC_TYPE: Code<Component, Primary> =
    Code::error(Component::Semantic, Primary::Type, 3);

// ============================================================================
// Usage
// ============================================================================

fn main() {
    println!("🦆 Documented Trait-Based Error Codes\n");
    println!("======================================\n");

    // Print error codes with their metadata
    print_code_with_docs(ERR_PARSER_SYNTAX);
    println!();
    print_code_with_docs(ERR_SEMANTIC_TYPE);
}

fn print_code_with_docs(code: Code<Component, Primary>) {
    println!("Code: {}", code.code());
    println!("Severity: {}", code.severity().as_str());
    println!();

    // Component metadata
    let component = code.component();
    println!("Component: {}", component.as_str());
    if let Some(desc) = component.description() {
        println!("  Description: {}", desc);
    }
    println!("  Tags: {:?}", component.tags());
    println!("  Examples:");
    for example in component.examples() {
        println!("    - {}", example);
    }
    println!();

    // Primary metadata
    let primary = code.primary();
    println!("Primary: {}", primary.as_str());
    if let Some(desc) = primary.description() {
        println!("  Description: {}", desc);
    }
    if !primary.related().is_empty() {
        println!("  Related: {:?}", primary.related());
    }
}