waddling-errors-hash
Deterministic hash computation for waddling-errors diagnostic codes
This is a shared utility crate that provides hash computation functionality for the waddling-errors ecosystem. It exists to enable compile-time hash embedding in procedural macros while keeping the same hash algorithm available at runtime.
Why Does This Crate Exist?
The waddling-errors system needs to compute short, deterministic hashes for error codes (e.g., E.AUTH.TOKEN.001 → hCF3I). These hashes are used for:
- Compact logging: Save space in logs with 5-char identifiers
- Network protocols: Efficient error transmission
- Quick lookups: Fast error code search and correlation
- URL-safe identifiers: Safe for all systems (alphanumeric only)
The Problem
Procedural macros (like diag!) run in a separate compilation context from your runtime code. They can't directly use your runtime library's functions. So if we want to compute hashes at compile time (for zero runtime cost), we need the hash logic in a place both can access.
The Solution
waddling-errors-hash is a small, standalone crate that:
- ✅ Can be used by proc macros at compile time
- ✅ Can be used by the runtime library
- ✅ Keeps the hash algorithm consistent between both
- ✅ Has minimal dependencies (
ahashonly) - ✅ Is
no_stdcompatible
Architecture
┌─────────────────────────────────┐
│ waddling-errors-macros │
│ (proc macro - compile time) │
│ │
│ uses hash to embed constants │
└────────────┬────────────────────┘
│
│ depends on
▼
┌─────────────────────────────────┐
│ waddling-errors-hash │◄─────────┐
│ (pure computation) │ │
│ │ │ depends on
│ • compute_hash() │ │
│ • verify_hash() │ │
└─────────────────────────────────┘ │
▲ │
│ depends on │
│ │
┌────────────┴────────────────────┐ │
│ waddling-errors │──────────┘
│ (runtime library) │
│ │
│ uses hash for doc generation │
└─────────────────────────────────┘
What Features Does This Give Users?
1. Zero Runtime Cost Hashes
use diag;
diag!
Benefit: Every error code gets a hash constant for free, computed once at build time.
2. Deterministic Across Builds
The same error code always produces the same hash, regardless of:
- Platform (Windows, Linux, macOS)
- Rust version
- Build configuration
- Time of compilation
Benefit: Hashes can be used in documentation, APIs, and protocols without changing.
3. Optional Runtime Verification
Benefit: Can validate hashes at runtime if needed, but not required.
4. Compact Error Representation
// Instead of sending full error in network protocol:
// Send compact version:
Client looks up the hash in a catalog to get full message/docs.
Benefit: Reduced bandwidth, i18n on client, security (no sensitive info in errors).
What Burden Does This Put on Users?
For End Users: Zero Burden 🎉
If you just use waddling-errors:
- ✅ Hash computation happens automatically at compile time
- ✅ Hash constants are always available (e.g.,
E_AUTH_TOKEN_001_HASH) - ✅ No extra dependencies in your binary (unless you enable
hashfeature) - ✅ No performance overhead
- ✅ Nothing to configure
Example:
use diag;
diag!
For Library Maintainers: Minimal
The only "burden" is having one extra crate in the workspace:
Pros:
- ✅ Clean separation of concerns
- ✅ Proc macros can compute hashes at compile time
- ✅ Runtime library can use same algorithm
- ✅ Easy to test in isolation
- ✅ Can be versioned independently if needed
Cons:
- ❌ One extra crate in workspace (adds ~200 lines of code)
- ❌ Slightly more complex dependency graph
But this complexity is internal - users never see it!
Algorithm Details
- Hash Function:
ahashwith fixed seed ("Waddling") - Output Length: 5 characters
- Character Set: Base62 (0-9, A-Z, a-z)
- Collision Space: 916,132,832 combinations (62^5)
- Deterministic: Yes - same input always produces same output
- Performance: ~50ns per hash on modern CPUs
Usage Examples
In Proc Macros (Compile Time)
// In waddling-errors-macros/src/diag.rs
use compute_hash;
let code = "E.AUTH.TOKEN.001";
let hash = compute_hash; // Computed at compile time
let hash_const = quote! ;
At Runtime
use compute_hash;
Verification
use verify_hash;
assert!;
Testing
# Run all tests
# Test with no_std
Feature Flags
default = ["std"]std: Enable standard library support (disable forno_std)
License
MIT OR Apache-2.0
See Also
waddling-errors- Main error handling librarywaddling-errors-macros- Procedural macros