waddling-errors 0.7.3

Structured, secure-by-default diagnostic codes for distributed systems with no_std and role-based documentation
Documentation
//! Ultra-minimal diagnostic code system for the Waddling ecosystem
//!
//! Provides a standardized 4-part diagnostic code format:
//!
//! **Format**: `SEVERITY.COMPONENT.PRIMARY.SEQUENCE`  `E.CRYPTO.SALT.001`
//!
//! # Quick Start
//!
//! ## Using Macros (Recommended)
//!
//! ```rust,ignore
//! use waddling_errors_macros::{component, diag, primary, sequence, setup};
//!
//! pub mod components {
//!     use waddling_errors_macros::component;
//!     component! { Auth { docs: "Authentication" } }
//! }
//!
//! pub mod primaries {
//!     use waddling_errors_macros::primary;
//!     primary! { Token { docs: "Token errors" } }
//! }
//!
//! pub mod sequences {
//!     use waddling_errors_macros::sequence;
//!     sequence! { EXPIRED(17) { description: "Token expired" } }
//! }
//!
//! setup! {
//!     components = crate::components,
//!     primaries = crate::primaries,
//!     sequences = crate::sequences,
//! }
//!
//! diag! {
//!     <json, html>, // Auto-register for doc generation
//!     E.Auth.Token.EXPIRED: {
//!         message: "JWT token expired at {{timestamp}}",
//!         fields: [timestamp],
//!         'CR 'Pub description: "Session expired. Please log in again.",
//!         'R role: "Public",
//!     },
//! }
//! ```
//!
//! See [waddling-errors-macros](https://docs.rs/waddling-errors-macros) for complete macro documentation.
//!
//! ## Manual Approach (Full Control)
//!
//! Define your component and primary enums:
//!
//! ```rust
//! use waddling_errors::prelude::*;
//!
//! #[derive(Debug, Copy, Clone)]
//! enum Component { Crypto, Network }
//!
//! impl ComponentId for Component {
//!     fn as_str(&self) -> &'static str {
//!         match self {
//!             Component::Crypto => "CRYPTO",
//!             Component::Network => "NETWORK",
//!         }
//!     }
//! }
//!
//! #[derive(Debug, Copy, Clone)]
//! enum Primary { Salt, Key, Timeout }
//!
//! impl PrimaryId for Primary {
//!     fn as_str(&self) -> &'static str {
//!         match self {
//!             Primary::Salt => "SALT",
//!             Primary::Key => "KEY",
//!             Primary::Timeout => "TIMEOUT",
//!         }
//!     }
//! }
//!
//! const ERR_SALT: Code<Component, Primary> = error(Component::Crypto, Primary::Salt, 1);
//! assert_eq!(ERR_SALT.code(), "E.CRYPTO.SALT.001");
//! ```
//!
//! # Sequence Conventions
//!
//! The Waddling ecosystem uses semantic sequence numbers:
//!
//! | Sequence | Meaning    | Example                           |
//! |----------|------------|-----------------------------------|
//! | 001      | MISSING    | Required item not provided        |
//! | 002      | MISMATCH   | Values don't match expected type  |
//! | 003      | INVALID    | Format/validation failed          |
//! | 021      | NOTFOUND   | Resource not found                |
//! | 025      | CORRUPTED  | Data corruption detected          |
//! | 031-897  | (project)  | Domain-specific sequences         |
//! | 999      | COMPLETE   | Full completion                   |
//!
//! See `docs/SEQUENCE-CONVENTIONS.md` for complete list.
//!
//! # Error Registry Pattern
//!
//! ```rust
//! // errors.rs - Project error registry
//! use waddling_errors::prelude::*;
//!
//! #[derive(Debug, Copy, Clone)]
//! pub enum Component { Crypto, Parse }
//!
//! impl ComponentId for Component {
//!     fn as_str(&self) -> &'static str {
//!         match self {
//!             Component::Crypto => "CRYPTO",
//!             Component::Parse => "PARSE",
//!         }
//!     }
//! }
//!
//! #[derive(Debug, Copy, Clone)]
//! pub enum Primary { Salt, Length, Depr }
//!
//! impl PrimaryId for Primary {
//!     fn as_str(&self) -> &'static str {
//!         match self {
//!             Primary::Salt => "SALT",
//!             Primary::Length => "LENGTH",
//!             Primary::Depr => "DEPR",
//!         }
//!     }
//! }
//!
//! pub const SALT_MISSING: Code<Component, Primary> = error(Component::Crypto, Primary::Salt, 1);
//! pub const KEY_LENGTH: Code<Component, Primary> = error(Component::Crypto, Primary::Length, 2);
//! pub const DEPRECATED_SYNTAX: Code<Component, Primary> = warning(Component::Parse, Primary::Depr, 1);
//! ```

#![no_std]
#![forbid(unsafe_code)]

#[cfg(feature = "std")]
extern crate std;

#[cfg(not(feature = "std"))]
extern crate alloc;

mod code;
mod severity;
pub mod traits;

#[cfg(feature = "metadata")]
pub mod metadata;

#[cfg(all(feature = "metadata", feature = "std"))]
pub mod registry;

#[cfg(feature = "doc-gen")]
pub mod doc_generator;

// Internal utilities for macros - Hygiene support
#[doc(hidden)]
pub mod internal {
    #[cfg(feature = "auto-register")]
    pub use ctor;
}

// Re-export procedural macros
#[cfg(feature = "macros")]
pub use waddling_errors_macros::*;

pub use code::Code;
pub use severity::Severity;
pub use traits::{
    ComponentId, ComponentIdDocumented, ErrorMetadata, FieldMeta, PrimaryId, PrimaryIdDocumented,
    Role,
};

// Top-level convenience functions (generic over ComponentId/PrimaryId)

/// Create an error code
pub const fn error<C: ComponentId, P: PrimaryId>(
    component: C,
    primary: P,
    sequence: u16,
) -> Code<C, P> {
    Code::error(component, primary, sequence)
}

/// Create a warning code
pub const fn warning<C: ComponentId, P: PrimaryId>(
    component: C,
    primary: P,
    sequence: u16,
) -> Code<C, P> {
    Code::warning(component, primary, sequence)
}

/// Create a critical code
pub const fn critical<C: ComponentId, P: PrimaryId>(
    component: C,
    primary: P,
    sequence: u16,
) -> Code<C, P> {
    Code::critical(component, primary, sequence)
}

/// Create a blocked code
pub const fn blocked<C: ComponentId, P: PrimaryId>(
    component: C,
    primary: P,
    sequence: u16,
) -> Code<C, P> {
    Code::blocked(component, primary, sequence)
}

/// Create a help code
pub const fn help<C: ComponentId, P: PrimaryId>(
    component: C,
    primary: P,
    sequence: u16,
) -> Code<C, P> {
    Code::help(component, primary, sequence)
}

/// Create a success code
pub const fn success<C: ComponentId, P: PrimaryId>(
    component: C,
    primary: P,
    sequence: u16,
) -> Code<C, P> {
    Code::success(component, primary, sequence)
}

/// Create a completed code
pub const fn completed<C: ComponentId, P: PrimaryId>(
    component: C,
    primary: P,
    sequence: u16,
) -> Code<C, P> {
    Code::completed(component, primary, sequence)
}

/// Create an info code
pub const fn info<C: ComponentId, P: PrimaryId>(
    component: C,
    primary: P,
    sequence: u16,
) -> Code<C, P> {
    Code::info(component, primary, sequence)
}

/// Create a trace code
pub const fn trace<C: ComponentId, P: PrimaryId>(
    component: C,
    primary: P,
    sequence: u16,
) -> Code<C, P> {
    Code::trace(component, primary, sequence)
}

// Prelude module

/// Commonly used types and functions
///
/// ```rust
/// use waddling_errors::prelude::*;
///
/// #[derive(Debug, Copy, Clone)]
/// enum MyComponent { Auth, Database }
///
/// impl ComponentId for MyComponent {
///     fn as_str(&self) -> &'static str {
///         match self { MyComponent::Auth => "AUTH", MyComponent::Database => "DATABASE" }
///     }
/// }
///
/// #[derive(Debug, Copy, Clone)]
/// enum MyPrimary { Token, Connection }
///
/// impl PrimaryId for MyPrimary {
///     fn as_str(&self) -> &'static str {
///         match self { MyPrimary::Token => "TOKEN", MyPrimary::Connection => "CONN" }
///     }
/// }
///
/// const ERR: Code<MyComponent, MyPrimary> = error(MyComponent::Auth, MyPrimary::Token, 1);
/// ```
/// Prelude module for convenient imports
pub mod prelude {
    pub use crate::{Code, Severity};
    pub use crate::{ComponentId, PrimaryId};
    pub use crate::{blocked, completed, critical, error, help, info, success, trace, warning};
}