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(all(feature = "metadata", feature = "std"))]
112pub mod registry;
113
114#[cfg(feature = "doc-gen")]
115pub mod doc_generator;
116
117#[cfg(feature = "hash")]
118pub(crate) mod hash;
119
120// Re-export procedural macros
121#[cfg(feature = "macros")]
122pub use waddling_errors_macros::*;
123
124pub use code::Code;
125pub use severity::Severity;
126pub use traits::{
127 ComponentId, ComponentIdDocumented, ErrorMetadata, FieldMeta, PrimaryId, PrimaryIdDocumented,
128 Role,
129};
130
131// Top-level convenience functions (generic over ComponentId/PrimaryId)
132
133/// Create an error code
134pub const fn error<C: ComponentId, P: PrimaryId>(
135 component: C,
136 primary: P,
137 sequence: u16,
138) -> Code<C, P> {
139 Code::error(component, primary, sequence)
140}
141
142/// Create a warning code
143pub const fn warning<C: ComponentId, P: PrimaryId>(
144 component: C,
145 primary: P,
146 sequence: u16,
147) -> Code<C, P> {
148 Code::warning(component, primary, sequence)
149}
150
151/// Create a critical code
152pub const fn critical<C: ComponentId, P: PrimaryId>(
153 component: C,
154 primary: P,
155 sequence: u16,
156) -> Code<C, P> {
157 Code::critical(component, primary, sequence)
158}
159
160/// Create a blocked code
161pub const fn blocked<C: ComponentId, P: PrimaryId>(
162 component: C,
163 primary: P,
164 sequence: u16,
165) -> Code<C, P> {
166 Code::blocked(component, primary, sequence)
167}
168
169/// Create a help code
170pub const fn help<C: ComponentId, P: PrimaryId>(
171 component: C,
172 primary: P,
173 sequence: u16,
174) -> Code<C, P> {
175 Code::help(component, primary, sequence)
176}
177
178/// Create a success code
179pub const fn success<C: ComponentId, P: PrimaryId>(
180 component: C,
181 primary: P,
182 sequence: u16,
183) -> Code<C, P> {
184 Code::success(component, primary, sequence)
185}
186
187/// Create a completed code
188pub const fn completed<C: ComponentId, P: PrimaryId>(
189 component: C,
190 primary: P,
191 sequence: u16,
192) -> Code<C, P> {
193 Code::completed(component, primary, sequence)
194}
195
196/// Create an info code
197pub const fn info<C: ComponentId, P: PrimaryId>(
198 component: C,
199 primary: P,
200 sequence: u16,
201) -> Code<C, P> {
202 Code::info(component, primary, sequence)
203}
204
205/// Create a trace code
206pub const fn trace<C: ComponentId, P: PrimaryId>(
207 component: C,
208 primary: P,
209 sequence: u16,
210) -> Code<C, P> {
211 Code::trace(component, primary, sequence)
212}
213
214// Prelude module
215
216/// Commonly used types and functions
217///
218/// ```rust
219/// use waddling_errors::prelude::*;
220///
221/// #[derive(Debug, Copy, Clone)]
222/// enum MyComponent { Auth, Database }
223///
224/// impl ComponentId for MyComponent {
225/// fn as_str(&self) -> &'static str {
226/// match self { MyComponent::Auth => "AUTH", MyComponent::Database => "DATABASE" }
227/// }
228/// }
229///
230/// #[derive(Debug, Copy, Clone)]
231/// enum MyPrimary { Token, Connection }
232///
233/// impl PrimaryId for MyPrimary {
234/// fn as_str(&self) -> &'static str {
235/// match self { MyPrimary::Token => "TOKEN", MyPrimary::Connection => "CONN" }
236/// }
237/// }
238///
239/// const ERR: Code<MyComponent, MyPrimary> = error(MyComponent::Auth, MyPrimary::Token, 1);
240/// ```
241/// Prelude module for convenient imports
242pub mod prelude {
243 pub use crate::{Code, Severity};
244 pub use crate::{ComponentId, PrimaryId};
245 pub use crate::{blocked, completed, critical, error, help, info, success, trace, warning};
246}