# Waddling-Errors Core Usage Guide
**Version**: 0.7.x
**Last Updated**: January 6, 2026
---
## Table of Contents
1. [Introduction](#introduction)
2. [Installation](#installation)
3. [Core Concepts](#core-concepts)
4. [Quick Start](#quick-start)
5. [Defining Error Codes](#defining-error-codes)
6. [Working with Severity Levels](#working-with-severity-levels)
7. [Using Error Codes in Your Application](#using-error-codes-in-your-application)
8. [Advanced Features](#advanced-features)
9. [Integration Patterns](#integration-patterns)
10. [Best Practices](#best-practices)
11. [Troubleshooting](#troubleshooting)
---
## Introduction
`waddling-errors` is a type-safe diagnostic code system that provides structured, consistent error codes with a 4-part format:
```
SEVERITY.COMPONENT.PRIMARY.SEQUENCE
```
**Example:** `E.AUTH.TOKEN.001` (Error in Auth component, Token category, sequence 001)
### Key Design Principles
- **Type-Safe**: Define your own component/primary enums with compile-time checking
- **Zero Dependencies by Default**: Modular features for optional functionality
- **no_std Compatible**: Works in embedded and WASM environments
- **Semantic Methods**: Intelligent error handling with `is_blocking()`, `is_positive()`, `priority()`
- **Extensible**: Three levels of trait implementation from minimal to fully documented
---
## Installation
### Default Installation (no_std + alloc, includes macros)
```toml
[dependencies]
waddling-errors = "0.7"
```
### With Standard Library Features
```toml
[dependencies]
waddling-errors = { version = "0.7", features = ["std", "doc-gen", "hash", "serde"] }
```
### Pure no_std (No Allocator)
```toml
[dependencies]
waddling-errors = { version = "0.7", default-features = false }
```
### Feature Flags Quick Reference
| `macros` | Procedural macros (default) | waddling-errors-macros | Reduced boilerplate |
| `std` | Standard library support | None | File I/O, doc generation |
| `hash` | Base62 hash codes | waddling-errors-hash | Compact logging |
| `emoji` | Unicode emoji for severities | None | Visual terminal output |
| `ansi-colors` | Terminal color codes | None | Colored logs |
| `serde` | Serialization support | serde | JSON APIs, config files |
| `doc-gen` | HTML/JSON documentation | std, serde, serde_json | Auto-documentation |
| `metadata` | Compile-time metadata | paste | Documentation generation |
See [FEATURE_FLAGS.md](FEATURE_FLAGS.md) for detailed feature information.
---
## Core Concepts
### 1. The 4-Part Format
Every diagnostic code consists of four parts:
```
[SEVERITY].[COMPONENT].[PRIMARY].[SEQUENCE]
```
- **SEVERITY**: Single-character code (E/W/C/B/S/K/I/T/H)
- **COMPONENT**: Your application's modules/areas (2-12 chars, uppercase)
- **PRIMARY**: Error categories within components (2-12 chars, uppercase)
- **SEQUENCE**: 3-digit number (001-999) with semantic meaning
### 2. Type-Safe Design
Instead of strings, you define Rust enums for components and primaries:
```rust
#[derive(Debug, Copy, Clone)]
enum Component { Auth, Parser, Database }
#[derive(Debug, Copy, Clone)]
enum Primary { Token, Syntax, Connection }
```
This provides:
- Compile-time validation
- IDE autocomplete
- Pattern matching support
- Refactoring safety
### 3. Three Levels of Traits
Choose the level that fits your needs:
**Level 1: Minimal (Required)**
- Implement `ComponentId` and `PrimaryId` traits
- Just need `.as_str()` method
- Perfect for basic error codes
**Level 2: Documented (Optional)**
- Add `ComponentIdDocumented` and `PrimaryIdDocumented`
- Provides description, tags, and examples
- Good for basic documentation
**Level 3: Full Metadata (Optional)**
- Implement `ErrorMetadata` for rich documentation
- Includes messages, solutions, roles, deprecation
- Enables full documentation generation
---
## Quick Start
### Step 1: Define Your Error Structure
```rust
use waddling_errors::prelude::*;
// Define your components (modules/areas of your application)
#[derive(Debug, Copy, Clone)]
enum Component {
Auth,
Parser,
Database,
}
impl ComponentId for Component {
fn as_str(&self) -> &'static str {
match self {
Component::Auth => "AUTH",
Component::Parser => "PARSER",
Component::Database => "DB",
}
}
}
// Define your primary categories (error types within components)
#[derive(Debug, Copy, Clone)]
enum Primary {
Token,
Syntax,
Connection,
}
impl PrimaryId for Primary {
fn as_str(&self) -> &'static str {
match self {
Primary::Token => "TOKEN",
Primary::Syntax => "SYNTAX",
Primary::Connection => "CONN",
}
}
}
```
### Step 2: Create Error Code Constants
```rust
// Create error codes using constructor functions
const ERR_TOKEN_MISSING: Code<Component, Primary> =
Code::error(Component::Auth, Primary::Token, 1);
const ERR_TOKEN_INVALID: Code<Component, Primary> =
Code::error(Component::Auth, Primary::Token, 3);
const ERR_SYNTAX_INVALID: Code<Component, Primary> =
Code::error(Component::Parser, Primary::Syntax, 3);
const WARN_DB_SLOW: Code<Component, Primary> =
Code::warning(Component::Database, Primary::Connection, 18);
// Or use the shorthand functions
const ERR_DB_TIMEOUT: Code<Component, Primary> =
error(Component::Database, Primary::Connection, 17);
```
### Step 3: Use Error Codes
```rust
fn authenticate(token: Option<&str>) -> Result<String, Code<Component, Primary>> {
let token = token.ok_or(ERR_TOKEN_MISSING)?;
if token.is_empty() {
return Err(ERR_TOKEN_INVALID);
}
Ok("user123".to_string())
}
fn main() {
match authenticate(None) {
Ok(user) => println!("✅ Authenticated: {}", user),
Err(code) => {
println!("❌ Error: {}", code.code());
println!(" Priority: {}", code.severity().priority());
println!(" Blocking: {}", code.severity().is_blocking());
}
}
// Output:
// ❌ Error: E.AUTH.TOKEN.001
// Priority: 8
// Blocking: true
}
```
---
## Defining Error Codes
### Constructor Methods
The `Code` struct provides constructor methods for each severity:
```rust
use waddling_errors::Code;
// Error (E) - Operation failed
const ERR: Code<Component, Primary> =
Code::error(Component::Auth, Primary::Token, 1);
// Warning (W) - Potential issue
const WARN: Code<Component, Primary> =
Code::warning(Component::Auth, Primary::Token, 10);
// Critical (C) - Severe issue requiring attention
const CRIT: Code<Component, Primary> =
Code::critical(Component::Database, Primary::Connection, 25);
// Blocked (B) - Execution blocked/waiting
const BLOCKED: Code<Component, Primary> =
Code::blocked(Component::Database, Primary::Connection, 15);
// Success (S) - Operation succeeded
const SUCCESS: Code<Component, Primary> =
Code::success(Component::Auth, Primary::Token, 999);
// Completed (K) - Task/phase completed
const COMPLETED: Code<Component, Primary> =
Code::completed(Component::Parser, Primary::Syntax, 999);
// Info (I) - Informational events
const INFO: Code<Component, Primary> =
Code::info(Component::Parser, Primary::Syntax, 1);
// Trace (T) - Execution traces
const TRACE: Code<Component, Primary> =
Code::trace(Component::Parser, Primary::Syntax, 100);
// Help (H) - Helpful suggestions
const HELP: Code<Component, Primary> =
Code::help(Component::Auth, Primary::Token, 1);
```
### Top-Level Convenience Functions
For less verbose code, use the prelude functions:
```rust
use waddling_errors::prelude::*;
const ERR: Code<Component, Primary> = error(Component::Auth, Primary::Token, 1);
const WARN: Code<Component, Primary> = warning(Component::Auth, Primary::Token, 10);
const CRIT: Code<Component, Primary> = critical(Component::Database, Primary::Connection, 25);
```
### Using Sequence Conventions
Follow semantic sequence numbers for consistency:
```rust
// .001 = MISSING (required item not provided)
const ERR_TOKEN_MISSING: Code<Component, Primary> =
error(Component::Auth, Primary::Token, 1);
// .003 = INVALID (validation failed)
const ERR_TOKEN_INVALID: Code<Component, Primary> =
error(Component::Auth, Primary::Token, 3);
// .017 = TIMEOUT (operation timed out)
const ERR_TOKEN_TIMEOUT: Code<Component, Primary> =
error(Component::Auth, Primary::Token, 17);
// .021 = NOTFOUND (resource not found)
const ERR_USER_NOT_FOUND: Code<Component, Primary> =
error(Component::Auth, Primary::Token, 21);
// .025 = CORRUPTED (data corruption detected)
const CRIT_DB_CORRUPTED: Code<Component, Primary> =
critical(Component::Database, Primary::Connection, 25);
// .999 = COMPLETE (full completion)
const SUCCESS_AUTH: Code<Component, Primary> =
success(Component::Auth, Primary::Token, 999);
```
See [SEQUENCE-CONVENTIONS.md](SEQUENCE-CONVENTIONS.md) for the complete list.
---
## Working with Severity Levels
### The Nine Severity Levels
| **Error** | `E` | 8 | Yes | Invalid input, logic errors |
| **Blocked** | `B` | 7 | Yes | Deadlock, I/O wait, network down |
| **Critical** | `C` | 6 | No | Data corruption, resource exhaustion |
| **Warning** | `W` | 5 | No | Deprecated API, edge cases |
| **Help** | `H` | 4 | No | Helpful suggestions, tips |
| **Success** | `S` | 3 | No | Operation succeeded |
| **Completed** | `K` | 2 | No | Task/phase finished |
| **Info** | `I` | 1 | No | Events, milestones, status |
| **Trace** | `T` | 0 | No | Execution traces, probes, timing |
### Severity Methods
```rust
use waddling_errors::Severity;
let severity = Severity::Error;
// Get string representations
severity.as_char(); // 'E'
severity.as_str(); // "Error"
severity.description(); // "Operation failed"
// Get priority (0-8 scale, higher = more severe)
severity.priority(); // 8
// Semantic checks
severity.is_blocking(); // true - stops execution
severity.is_negative(); // true - indicates failure
severity.is_positive(); // false - not a success
severity.is_neutral(); // false - not info/trace
// Visual output (with features)
#[cfg(feature = "emoji")]
severity.emoji(); // "❌"
#[cfg(feature = "ansi-colors")]
severity.ansi_color(); // "\x1b[1;31m" (red)
```
### Priority-Based Handling
Use priority for intelligent error handling:
```rust
fn handle_error(code: Code<Component, Primary>) {
match code.severity().priority() {
8 => {
// Error - Stop execution
eprintln!("❌ CRITICAL: {}", code.code());
std::process::exit(1);
}
7 => {
// Blocked - Retry logic
eprintln!("⏸️ BLOCKED: {}", code.code());
// Implement retry...
}
5..=6 => {
// Warning/Critical - Log and continue
eprintln!("⚠️ WARNING: {}", code.code());
}
0..=4 => {
// Info/Help/Success - Log only
println!("ℹ️ {}", code.code());
}
_ => {}
}
}
```
### Blocking vs Non-Blocking
```rust
fn process(code: Code<Component, Primary>) -> Result<(), String> {
if code.severity().is_blocking() {
// Error or Blocked - stop execution
return Err(format!("Cannot continue: {}", code.code()));
}
if code.severity().is_negative() {
// Warning/Critical - log but continue
eprintln!("⚠️ Issue detected: {}", code.code());
}
Ok(())
}
```
---
## Using Error Codes in Your Application
### In Result Types
```rust
type AppResult<T> = Result<T, Code<Component, Primary>>;
fn parse_config(path: &str) -> AppResult<Config> {
let content = read_file(path)
.map_err(|_| ERR_CONFIG_NOT_FOUND)?;
parse_yaml(&content)
.map_err(|_| ERR_CONFIG_INVALID)?;
// ...
}
```
### Pattern Matching on Components
```rust
fn handle_error(code: Code<Component, Primary>) {
match code.component() {
Component::Auth => {
println!("Authentication error: {}", code.code());
// Send to auth service
}
Component::Database => {
println!("Database error: {}", code.code());
// Check connection pool
}
Component::Parser => {
println!("Parse error: {}", code.code());
// Show syntax help
}
}
}
```
### Extracting Code Parts
```rust
let code = ERR_TOKEN_MISSING;
// Get full code string
assert_eq!(code.code(), "E.AUTH.TOKEN.001");
// Access individual parts
assert_eq!(code.severity().as_char(), 'E');
assert_eq!(code.component_str(), "AUTH");
assert_eq!(code.primary_str(), "TOKEN");
assert_eq!(code.sequence(), 1);
```
### Zero-Allocation Formatting
For performance-critical paths:
```rust
use core::fmt::Write;
let code = ERR_TOKEN_MISSING;
let mut buffer = String::new();
// Write without allocating
code.write_code(&mut buffer).unwrap();
assert_eq!(buffer, "E.AUTH.TOKEN.001");
```
### Using with Hash Codes (Optional)
```toml
waddling-errors = { version = "0.7", features = ["hash"] }
```
```rust
let code = ERR_TOKEN_MISSING;
// Get 5-character base62 hash
let hash = code.hash(); // e.g., "jGKFp"
// Use in logs for quick searches
log::error!("#{} Authentication failed", hash);
// Search logs: grep "jGKFp" logs/
```
---
## Advanced Features
### 1. Documentation Generation
Enable doc generation features:
```toml
waddling-errors = { version = "0.7", features = ["std", "doc-gen", "metadata"] }
```
Create a documentation registry:
```rust
use waddling_errors::doc_generator::{DocRegistry, JsonRenderer, HtmlRenderer};
use waddling_errors::Role;
let mut registry = DocRegistry::new("My API", "1.0.0");
// Register components
registry.register_component(
"AUTH",
Some("Authentication system"),
&[],
&["security"]
)?;
// Register error codes
registry.register_code_extended(
&ERR_TOKEN_MISSING,
"JWT token missing from Authorization header",
&["Include Authorization: Bearer <token> header"],
&["auth", "security"],
Some(Role::Public),
&[],
None,
&[],
)?;
// Generate documentation
registry.render_all_roles(
vec![Box::new(JsonRenderer), Box::new(HtmlRenderer::new())],
"target/docs"
)?;
```
See [DOC_GENERATION_GUIDE.md](DOC_GENERATION_GUIDE.md) for details.
### 2. Role-Based Visibility
Control what information is exposed to different audiences:
```rust
use waddling_errors::Role;
// Public - End users
registry.register_code_extended(
&ERR_TOKEN_MISSING,
"Your session has expired. Please log in again.",
&["Click the login button to authenticate"],
&["auth"],
Some(Role::Public),
&[], None, &[],
)?;
// Developer - Contributors
registry.register_code_extended(
&ERR_DB_CONNECTION,
"Database connection pool exhausted",
&["Check connection pool size", "Monitor active connections"],
&["database", "performance"],
Some(Role::Developer),
&[], None, &[],
)?;
// Internal - Full team
registry.register_code_extended(
&ERR_CRYPTO_KEY,
"Secret key rotation failed in HSM module",
&["Check HSM connectivity", "Verify key permissions"],
&["security", "crypto"],
Some(Role::Internal),
&[], None, &[],
)?;
```
### 3. Network Efficiency with Catalogs
Generate compact catalogs for IoT/mobile:
```rust
use waddling_errors::doc_generator::{CatalogRenderer, CatalogFormat};
let catalog = CatalogRenderer::new(CatalogFormat::Compact);
registry.render(vec![Box::new(catalog)], "target/catalog")?;
// Server sends:
// {"h":"jGKFp","f":{"temp":"45.2"}} // 40 bytes
// Client expands using catalog:
// "Temperature 45.2°C exceeds threshold" // 80% smaller payload!
```
See [CATALOG_GUIDE.md](CATALOG_GUIDE.md) for details.
### 4. Visual Output
Enable emoji and colors:
```toml
waddling-errors = { version = "0.7", features = ["emoji", "ansi-colors"] }
```
```rust
fn display_error(code: Code<Component, Primary>) {
let severity = code.severity();
#[cfg(feature = "emoji")]
print!("{} ", severity.emoji());
#[cfg(feature = "ansi-colors")]
print!("{}", severity.ansi_color());
print!("{}", code.code());
#[cfg(feature = "ansi-colors")]
print!("{}", Severity::ANSI_RESET);
println!();
}
// Output: ❌ E.AUTH.TOKEN.001 (in red)
```
---
## Integration Patterns
### With thiserror
```rust
use waddling_errors::prelude::*;
use thiserror::Error;
#[derive(Error, Debug)]
pub enum AppError {
#[error("{0}: {1}")]
Auth(String, String), // (code, message)
#[error("{0}: {1}")]
Database(String, String),
}
impl AppError {
fn from_code(code: Code<Component, Primary>, message: &str) -> Self {
match code.component() {
Component::Auth => AppError::Auth(code.code(), message.to_string()),
Component::Database => AppError::Database(code.code(), message.to_string()),
_ => AppError::Auth(code.code(), message.to_string()),
}
}
fn code(&self) -> &str {
match self {
AppError::Auth(code, _) => code,
AppError::Database(code, _) => code,
}
}
}
// Usage
fn authenticate(token: Option<&str>) -> Result<String, AppError> {
let token = token.ok_or_else(||
AppError::from_code(ERR_TOKEN_MISSING, "Token not provided")
)?;
Ok("user123".to_string())
}
```
### With anyhow
```rust
use anyhow::{Context, Result};
fn load_config() -> Result<Config> {
let content = read_file("config.yaml")
.with_context(|| format!("{}: Config file not found", ERR_CONFIG_NOT_FOUND.code()))?;
let config = parse_yaml(&content)
.with_context(|| format!("{}: Invalid YAML syntax", ERR_CONFIG_INVALID.code()))?;
Ok(config)
}
```
### With Custom Error Types
```rust
#[derive(Debug)]
pub struct ApiError {
code: Code<Component, Primary>,
message: String,
context: Option<String>,
}
impl ApiError {
pub fn new(code: Code<Component, Primary>, message: impl Into<String>) -> Self {
Self {
code,
message: message.into(),
context: None,
}
}
pub fn with_context(mut self, context: impl Into<String>) -> Self {
self.context = Some(context.into());
self
}
pub fn code(&self) -> &Code<Component, Primary> {
&self.code
}
}
impl std::fmt::Display for ApiError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}: {}", self.code.code(), self.message)?;
if let Some(ctx) = &self.context {
write!(f, " ({})", ctx)?;
}
Ok(())
}
}
impl std::error::Error for ApiError {}
```
---
## Best Practices
### 1. Organize Error Codes in a Module
Create a dedicated `errors.rs` or `codes.rs` module:
```rust
// src/errors.rs
use waddling_errors::prelude::*;
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Component {
Auth,
Api,
Database,
Cache,
Storage,
}
impl ComponentId for Component {
fn as_str(&self) -> &'static str {
match self {
Component::Auth => "AUTH",
Component::Api => "API",
Component::Database => "DB",
Component::Cache => "CACHE",
Component::Storage => "STORAGE",
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Primary {
Token,
Request,
Connection,
Data,
File,
}
impl PrimaryId for Primary {
fn as_str(&self) -> &'static str {
match self {
Primary::Token => "TOKEN",
Primary::Request => "REQUEST",
Primary::Connection => "CONN",
Primary::Data => "DATA",
Primary::File => "FILE",
}
}
}
// Authentication errors
pub const ERR_TOKEN_MISSING: Code<Component, Primary> =
error(Component::Auth, Primary::Token, 1);
pub const ERR_TOKEN_INVALID: Code<Component, Primary> =
error(Component::Auth, Primary::Token, 3);
pub const ERR_TOKEN_EXPIRED: Code<Component, Primary> =
error(Component::Auth, Primary::Token, 17);
// Database errors
pub const ERR_DB_NOT_FOUND: Code<Component, Primary> =
error(Component::Database, Primary::Connection, 21);
pub const ERR_DB_TIMEOUT: Code<Component, Primary> =
error(Component::Database, Primary::Connection, 17);
pub const CRIT_DB_CORRUPTED: Code<Component, Primary> =
critical(Component::Database, Primary::Data, 25);
```
### 2. Use Type Aliases
Create a project-specific Result type:
```rust
pub type AppCode = Code<Component, Primary>;
pub type AppResult<T> = Result<T, AppCode>;
```
### 3. Follow Sequence Conventions
Always use semantic sequence numbers:
```rust
// ✅ Good: Use .001 for "missing"
const ERR_TOKEN_MISSING: Code<Component, Primary> =
error(Component::Auth, Primary::Token, 1);
// ❌ Bad: Random sequence
const ERR_TOKEN_MISSING: Code<Component, Primary> =
error(Component::Auth, Primary::Token, 42);
```
### 4. Group Related Codes
```rust
// Group by component and primary
mod auth {
use super::*;
// Token errors
pub const TOKEN_MISSING: AppCode = error(Component::Auth, Primary::Token, 1);
pub const TOKEN_INVALID: AppCode = error(Component::Auth, Primary::Token, 3);
pub const TOKEN_EXPIRED: AppCode = error(Component::Auth, Primary::Token, 17);
// Permission errors
pub const PERMISSION_DENIED: AppCode = error(Component::Auth, Primary::Permission, 8);
}
mod database {
use super::*;
pub const CONNECTION_FAILED: AppCode = error(Component::Database, Primary::Connection, 1);
pub const CONNECTION_TIMEOUT: AppCode = error(Component::Database, Primary::Connection, 17);
pub const DATA_CORRUPTED: AppCode = critical(Component::Database, Primary::Data, 25);
}
```
### 5. Document Your Error Codes
Add documentation comments:
```rust
/// Authentication token is missing from the request
///
/// # Sequence: 001 (MISSING)
///
/// # Solution
/// Include the Authorization header:
/// ```
/// Authorization: Bearer <your-token>
/// ```
pub const ERR_TOKEN_MISSING: Code<Component, Primary> =
error(Component::Auth, Primary::Token, 1);
```
### 6. Use const fn Where Possible
All constructors are `const fn`, allowing compile-time evaluation:
```rust
// This is evaluated at compile time
const ERR: Code<Component, Primary> = error(Component::Auth, Primary::Token, 1);
// Can use in const contexts
const fn get_default_error() -> Code<Component, Primary> {
ERR
}
```
### 7. Leverage Pattern Matching
```rust
fn route_error(code: Code<Component, Primary>) {
match (code.component(), code.severity()) {
(Component::Auth, Severity::Error) => {
// Handle auth errors
send_to_auth_service(code);
}
(Component::Database, Severity::Critical) => {
// Handle critical DB issues
alert_oncall_team(code);
}
(_, Severity::Warning) => {
// Log warnings
log::warn!("{}", code.code());
}
_ => {
log::info!("{}", code.code());
}
}
}
```
---
## Troubleshooting
### Common Issues
#### 1. Sequence Must Be <= 999
```rust
// ❌ Error: Sequence must be <= 999
const ERR: Code<Component, Primary> = error(Component::Auth, Primary::Token, 1000);
// ✅ Fix: Use 001-999
const ERR: Code<Component, Primary> = error(Component::Auth, Primary::Token, 999);
```
#### 2. Component/Primary Name Too Long
```rust
// ❌ Names should be 2-12 characters
impl ComponentId for Component {
fn as_str(&self) -> &'static str {
"VERYLONGCOMPONENTNAME" // Too long!
}
}
// ✅ Use abbreviations
impl ComponentId for Component {
fn as_str(&self) -> &'static str {
"AUTH" // Good
}
}
```
#### 3. no_std Compilation Errors
If you get errors about `std` in a no_std environment:
```toml
# ❌ Wrong: Default features include std
waddling-errors = "0.7"
# ✅ Correct: Disable default features
waddling-errors = { version = "0.7", default-features = false }
```
#### 4. Missing Hash Method
```rust
// ❌ Error: no method named `hash` found
let hash = code.hash();
// ✅ Enable the hash feature
// Cargo.toml:
waddling-errors = { version = "0.7", features = ["hash"] }
```
#### 5. Doc Generation Not Working
```rust
// ❌ Error: cannot find module `doc_generator`
use waddling_errors::doc_generator::DocRegistry;
// ✅ Enable required features
// Cargo.toml:
waddling-errors = { version = "0.7", features = ["std", "doc-gen", "metadata"] }
```
---
## Examples
The repository includes comprehensive examples:
### Basic Examples
```bash
# Trait-based error codes
cargo run --example trait_based_enums
# With documentation metadata
cargo run --example trait_based_documented
```
### Complete System
```bash
# Full production example (6 components, 31 errors)
cargo run --example complete_system --features "doc-gen,hash,metadata"
```
### Integration Examples
```bash
# Integration with thiserror/anyhow patterns
cargo run --example integration_with_error_handling
```
### no_std Examples
```bash
# Pure no_std compatibility
cargo run --example no_std_example
# WASM target
cargo build --example wasm_minimal --target wasm32-unknown-unknown --no-default-features
```
### Documentation Examples
```bash
# HTML customization
cargo run --example html_customization_demo --features "doc-gen,metadata"
# Compile-time metadata
cargo run --example compile_time_metadata --features "doc-gen,metadata"
```
---
## Next Steps
1. **Read the Specifications**: Check [wdp-specs](../../wdp-specs/README.md) for the full Waddling Diagnostic Protocol
2. **Use Macros**: See [waddling-errors-macros](../../waddling-errors-macros/README.md) for reduced boilerplate
3. **Generate Documentation**: Follow [DOC_GENERATION_GUIDE.md](DOC_GENERATION_GUIDE.md)
4. **Customize HTML**: See [HTML_CUSTOMIZATION.md](HTML_CUSTOMIZATION.md)
5. **Learn Sequences**: Read [SEQUENCE-CONVENTIONS.md](SEQUENCE-CONVENTIONS.md)
---
## Additional Resources
- [API Documentation](https://docs.rs/waddling-errors)
- [Changelog](../CHANGELOG.md)
- [Contributing Guide](../../wdp-specs/CONTRIBUTING.md)
- [WDP Specifications](../../wdp-specs/README.md)
---
## License
Dual-licensed under MIT or Apache-2.0. See [LICENSE-MIT](../../LICENSE-MIT) and [LICENSE-APACHE](../../LICENSE-APACHE).