waddling_errors/
lib.rs

1//! Ultra-minimal diagnostic code system for the Waddling ecosystem
2//!
3//! Provides a standardized 4-part diagnostic code format:
4//!
5//! **Format**: `SEVERITY.COMPONENT.PRIMARY.SEQUENCE`  `E.CRYPTO.SALT.001`
6//!
7//! # Quick Start
8//!
9//! Define your component and primary enums:
10//!
11//! ```rust
12//! use waddling_errors::prelude::*;
13//!
14//! #[derive(Debug, Copy, Clone)]
15//! enum Component { Crypto, Network }
16//!
17//! impl ComponentId for Component {
18//!     fn as_str(&self) -> &'static str {
19//!         match self {
20//!             Component::Crypto => "CRYPTO",
21//!             Component::Network => "NETWORK",
22//!         }
23//!     }
24//! }
25//!
26//! #[derive(Debug, Copy, Clone)]
27//! enum Primary { Salt, Key, Timeout }
28//!
29//! impl PrimaryId for Primary {
30//!     fn as_str(&self) -> &'static str {
31//!         match self {
32//!             Primary::Salt => "SALT",
33//!             Primary::Key => "KEY",
34//!             Primary::Timeout => "TIMEOUT",
35//!         }
36//!     }
37//! }
38//!
39//! const ERR_SALT: Code<Component, Primary> = error(Component::Crypto, Primary::Salt, 1);
40//! assert_eq!(ERR_SALT.code(), "E.CRYPTO.SALT.001");
41//! ```
42//!
43//! # Sequence Conventions
44//!
45//! The Waddling ecosystem uses semantic sequence numbers:
46//!
47//! | Sequence | Meaning    | Example                           |
48//! |----------|------------|-----------------------------------|
49//! | 001      | MISSING    | Required item not provided        |
50//! | 002      | MISMATCH   | Values don't match expected type  |
51//! | 003      | INVALID    | Format/validation failed          |
52//! | 021      | NOTFOUND   | Resource not found                |
53//! | 025      | CORRUPTED  | Data corruption detected          |
54//! | 031-897  | (project)  | Domain-specific sequences         |
55//! | 999      | COMPLETE   | Full completion                   |
56//!
57//! See `docs/SEQUENCE-CONVENTIONS.md` for complete list.
58//!
59//! # Error Registry Pattern
60//!
61//! ```rust
62//! // errors.rs - Project error registry
63//! use waddling_errors::prelude::*;
64//!
65//! #[derive(Debug, Copy, Clone)]
66//! pub enum Component { Crypto, Parse }
67//!
68//! impl ComponentId for Component {
69//!     fn as_str(&self) -> &'static str {
70//!         match self {
71//!             Component::Crypto => "CRYPTO",
72//!             Component::Parse => "PARSE",
73//!         }
74//!     }
75//! }
76//!
77//! #[derive(Debug, Copy, Clone)]
78//! pub enum Primary { Salt, Length, Depr }
79//!
80//! impl PrimaryId for Primary {
81//!     fn as_str(&self) -> &'static str {
82//!         match self {
83//!             Primary::Salt => "SALT",
84//!             Primary::Length => "LENGTH",
85//!             Primary::Depr => "DEPR",
86//!         }
87//!     }
88//! }
89//!
90//! pub const SALT_MISSING: Code<Component, Primary> = error(Component::Crypto, Primary::Salt, 1);
91//! pub const KEY_LENGTH: Code<Component, Primary> = error(Component::Crypto, Primary::Length, 2);
92//! pub const DEPRECATED_SYNTAX: Code<Component, Primary> = warning(Component::Parse, Primary::Depr, 1);
93//! ```
94
95#![no_std]
96#![forbid(unsafe_code)]
97
98#[cfg(feature = "std")]
99extern crate std;
100
101#[cfg(not(feature = "std"))]
102extern crate alloc;
103
104mod code;
105mod severity;
106pub mod traits;
107
108#[cfg(feature = "metadata")]
109pub mod metadata;
110
111#[cfg(feature = "doc-gen")]
112pub mod doc_generator;
113
114#[cfg(feature = "hash")]
115pub(crate) mod hash;
116
117pub use code::Code;
118pub use severity::Severity;
119pub use traits::{
120    ComponentId, ComponentIdDocumented, ErrorMetadata, FieldMeta, PrimaryId, PrimaryIdDocumented,
121    Role,
122};
123
124// Top-level convenience functions (generic over ComponentId/PrimaryId)
125
126/// Create an error code
127pub const fn error<C: ComponentId, P: PrimaryId>(
128    component: C,
129    primary: P,
130    sequence: u16,
131) -> Code<C, P> {
132    Code::error(component, primary, sequence)
133}
134
135/// Create a warning code
136pub const fn warning<C: ComponentId, P: PrimaryId>(
137    component: C,
138    primary: P,
139    sequence: u16,
140) -> Code<C, P> {
141    Code::warning(component, primary, sequence)
142}
143
144/// Create a critical code
145pub const fn critical<C: ComponentId, P: PrimaryId>(
146    component: C,
147    primary: P,
148    sequence: u16,
149) -> Code<C, P> {
150    Code::critical(component, primary, sequence)
151}
152
153/// Create a blocked code
154pub const fn blocked<C: ComponentId, P: PrimaryId>(
155    component: C,
156    primary: P,
157    sequence: u16,
158) -> Code<C, P> {
159    Code::blocked(component, primary, sequence)
160}
161
162/// Create a help code
163pub const fn help<C: ComponentId, P: PrimaryId>(
164    component: C,
165    primary: P,
166    sequence: u16,
167) -> Code<C, P> {
168    Code::help(component, primary, sequence)
169}
170
171/// Create a success code
172pub const fn success<C: ComponentId, P: PrimaryId>(
173    component: C,
174    primary: P,
175    sequence: u16,
176) -> Code<C, P> {
177    Code::success(component, primary, sequence)
178}
179
180/// Create a completed code
181pub const fn completed<C: ComponentId, P: PrimaryId>(
182    component: C,
183    primary: P,
184    sequence: u16,
185) -> Code<C, P> {
186    Code::completed(component, primary, sequence)
187}
188
189/// Create an info code
190pub const fn info<C: ComponentId, P: PrimaryId>(
191    component: C,
192    primary: P,
193    sequence: u16,
194) -> Code<C, P> {
195    Code::info(component, primary, sequence)
196}
197
198/// Create a trace code
199pub const fn trace<C: ComponentId, P: PrimaryId>(
200    component: C,
201    primary: P,
202    sequence: u16,
203) -> Code<C, P> {
204    Code::trace(component, primary, sequence)
205}
206
207// Prelude module
208
209/// Commonly used types and functions
210///
211/// ```rust
212/// use waddling_errors::prelude::*;
213///
214/// #[derive(Debug, Copy, Clone)]
215/// enum MyComponent { Auth, Database }
216///
217/// impl ComponentId for MyComponent {
218///     fn as_str(&self) -> &'static str {
219///         match self { MyComponent::Auth => "AUTH", MyComponent::Database => "DATABASE" }
220///     }
221/// }
222///
223/// #[derive(Debug, Copy, Clone)]
224/// enum MyPrimary { Token, Connection }
225///
226/// impl PrimaryId for MyPrimary {
227///     fn as_str(&self) -> &'static str {
228///         match self { MyPrimary::Token => "TOKEN", MyPrimary::Connection => "CONN" }
229///     }
230/// }
231///
232/// const ERR: Code<MyComponent, MyPrimary> = error(MyComponent::Auth, MyPrimary::Token, 1);
233/// ```
234/// Prelude module for convenient imports
235pub mod prelude {
236    pub use crate::{Code, Severity};
237    pub use crate::{ComponentId, PrimaryId};
238    pub use crate::{blocked, completed, critical, error, help, info, success, trace, warning};
239}