Skip to main content

domain_key/
lib.rs

1//! # domain-key 🚀
2//!
3//! **High-performance, type-safe, domain-agnostic key system for Rust applications.**
4//!
5//! domain-key provides a flexible and efficient foundation for creating domain-specific keys
6//! with compile-time type safety, runtime validation, and extensive performance optimizations.
7//! This library focuses on zero-cost abstractions and maximum performance through feature-based
8//! optimization profiles.
9//!
10//! ## ✨ Key Features
11//!
12//! - **🔒 Type Safety**: Different key types cannot be mixed at compile time
13//! - **🏎️ High Performance**: Up to 75% performance improvements through advanced optimizations
14//! - **🎯 Domain Agnostic**: No built-in assumptions about specific domains
15//! - **💾 Memory Efficient**: Smart string handling with stack allocation for short keys
16//! - **🛡️ `DoS` Resistant**: Optional protection against `HashDoS` attacks
17//! - **🔧 Extensible**: Easy to add new domains and validation rules
18//! - **📦 Zero-Cost Abstractions**: No runtime overhead for type separation
19//!
20//! ## 🏗️ Architecture Overview
21//!
22//! ```text
23//! ┌─────────────────────────────────────────────────────────────────┐
24//! │                     APPLICATION LAYER                          │
25//! │  Business Logic  │  Domain Models  │  API Endpoints            │
26//! └─────────────────┬───────────────────┬───────────────────────────┘
27//!                   │                   │
28//!                   ▼                   ▼
29//! ┌─────────────────────────────────────────────────────────────────┐
30//! │                   TYPE SAFETY LAYER                            │
31//! │  Key<UserDomain> │ Key<SessionDomain> │ Key<CacheDomain>        │
32//! └─────────────────┬───────────────────────────────────────────────┘
33//!                   │
34//!                   ▼
35//! ┌─────────────────────────────────────────────────────────────────┐
36//! │                 PERFORMANCE LAYER                              │
37//! │  Stack Alloc │ Caching │ Specialized Ops │ Thread-Local        │
38//! └─────────────────┬───────────────────────────────────────────────┘
39//!                   │
40//!                   ▼
41//! ┌─────────────────────────────────────────────────────────────────┐
42//! │                  STORAGE LAYER                                 │
43//! │  SmartString + Cached Hash + Cached Length + Optimizations     │
44//! └─────────────────────────────────────────────────────────────────┘
45//! ```
46//!
47//! ## 🚀 Quick Start
48//!
49//! Add to your `Cargo.toml`:
50//!
51//! ```toml
52//! [dependencies]
53//! domain-key = { version = "0.2", features = ["fast"] }
54//! ```
55//!
56//! Define a domain and create keys:
57//!
58//! ```rust
59//! use domain_key::{Key, Domain, KeyDomain};
60//!
61//! // 1. Define your domain
62//! #[derive(Debug)]
63//! struct UserDomain;
64//!
65//! impl Domain for UserDomain {
66//!     const DOMAIN_NAME: &'static str = "user";
67//! }
68//!
69//! impl KeyDomain for UserDomain {
70//!     const MAX_LENGTH: usize = 32;
71//!     const TYPICALLY_SHORT: bool = true; // Optimization hint
72//! }
73//!
74//! // 2. Create a type alias
75//! type UserKey = Key<UserDomain>;
76//!
77//! // 3. Use it!
78//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
79//! let user_key = UserKey::new("john_doe")?;
80//! let composed_key = UserKey::from_parts(&["user", "123", "profile"], "_")?;
81//!
82//! println!("Domain: {}", user_key.domain());
83//! println!("Length: {}", user_key.len()); // O(1) with optimizations
84//! println!("Key: {}", user_key.as_str());
85//! # Ok(())
86//! # }
87//! ```
88//!
89//! ## Identifier Types
90//!
91//! domain-key provides three typed identifier wrappers:
92//!
93//! | Type | Storage | Use case |
94//! |------|---------|----------|
95//! | [`Key<D>`] | `SmartString` | Human-readable keys with validation |
96//! | [`Id<D>`] | `NonZeroU64` | Numeric database IDs (8 bytes, `Copy`) |
97//! | [`Uuid<D>`] | `uuid::Uuid` | UUID identifiers (16 bytes, `Copy`, feature `uuid`) |
98//!
99//! ```rust
100//! use domain_key::prelude::*;
101//!
102//! // Numeric IDs
103//! define_id_domain!(UserIdDomain, "user");
104//! id_type!(UserId, UserIdDomain);
105//!
106//! let id = UserId::new(42).unwrap();
107//! assert_eq!(id.get(), 42);
108//!
109//! // Or use the shorthand:
110//! define_id!(OrderIdDomain => OrderId);
111//! let order = OrderId::new(1).unwrap();
112//! ```
113//!
114//! All three types are domain-typed: `UserId` and `OrderId` are incompatible
115//! at compile time even though both wrap a `NonZeroU64`.
116//!
117//! ## Performance Features
118//!
119//! ### Feature-Based Optimization Profiles
120//!
121//! ```toml
122//! # Maximum performance (modern CPUs with AES-NI)
123//! features = ["fast"]
124//!
125//! # DoS protection + good performance
126//! features = ["secure"]
127//!
128//! # Cryptographic security
129//! features = ["crypto"]
130//!
131//! # All optimizations enabled
132//! features = ["fast", "std", "serde"]
133//! ```
134//!
135//! ### Build for Maximum Performance
136//!
137//! ```bash
138//! # Enable CPU-specific optimizations
139//! RUSTFLAGS="-C target-cpu=native" cargo build --release --features="fast"
140//! ```
141//!
142//! ### Performance Improvements
143//!
144//! | Operation | Standard | Optimized | Improvement |
145//! |-----------|----------|-----------|-------------|
146//! | Key Creation (short) | 100% | 128% | **28% faster** |
147//! | String Operations | 100% | 175% | **75% faster** |
148//! | Hash Operations | 100% | 140% | **40% faster** |
149//! | Length Access | O(n) | O(1) | **Constant time** |
150//!
151//! ## 📖 Advanced Examples
152//!
153//! ### Performance-Optimized Usage
154//!
155//! ```rust
156//! use domain_key::{Key, Domain, KeyDomain};
157//!
158//! #[derive(Debug)]
159//! struct OptimizedDomain;
160//!
161//! impl Domain for OptimizedDomain {
162//!     const DOMAIN_NAME: &'static str = "optimized";
163//! }
164//!
165//! impl KeyDomain for OptimizedDomain {
166//!     const EXPECTED_LENGTH: usize = 16; // Optimization hint
167//!     const TYPICALLY_SHORT: bool = true; // Enable stack allocation
168//! }
169//!
170//! type OptimizedKey = Key<OptimizedDomain>;
171//!
172//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
173//! // Basic optimized key creation
174//! let user_key = OptimizedKey::new("user_12345")?;
175//! let session_key = OptimizedKey::new("session_abc123")?;
176//!
177//! // Batch operations with from_parts
178//! let user_ids = vec![1, 2, 3, 4, 5];
179//! let user_keys: Result<Vec<_>, _> = user_ids.iter()
180//!     .map(|&id| OptimizedKey::from_parts(&["user", &id.to_string()], "_"))
181//!     .collect();
182//! let user_keys = user_keys?;
183//!
184//! // Optimized operations for repeated use
185//! let key = OptimizedKey::new("user_profile_settings_theme")?;
186//! let parts: Vec<&str> = key.split('_').collect(); // Uses optimizations when available
187//! # Ok(())
188//! # }
189//! ```
190//!
191//! ## 🔧 Feature Flags Reference
192//!
193//! ### Hash Algorithm Features (choose one for best results)
194//!
195//! - `fast` - `GxHash` (40% faster, requires modern CPU with AES-NI)
196//! - `secure` - `AHash` (`DoS` protection, balanced performance)
197//! - `crypto` - Blake3 (cryptographically secure)
198//! - Default - Standard hasher (good compatibility)
199//!
200//! ### Identifier Features
201//!
202//! - `uuid` — enables `Uuid<D>` typed UUID identifiers
203//! - `uuid-v4` — enables `Uuid::new()` random UUID v4 generation
204//! - `uuid-v7` — enables `Uuid::now_v7()` time-ordered generation
205//!
206//! ### Core Features
207//!
208//! - `std` - Standard library support (enabled by default)
209//! - `serde` - Serialization support (enabled by default)
210//! - `no_std` - No standard library (disables std-dependent features)
211//!
212//! ## 🛡️ Security Considerations
213//!
214//! domain-key provides multiple levels of security depending on your needs:
215//!
216//! - **`DoS` Protection**: Use `secure` feature for `AHash` with `DoS` resistance
217//! - **Cryptographic Security**: Use `crypto` feature for Blake3 cryptographic hashing
218//! - **Input Validation**: Comprehensive validation pipeline with custom rules
219//! - **Type Safety**: Compile-time prevention of key type mixing
220//! - **Memory Safety**: Rust's ownership system + additional optimizations
221
222#![cfg_attr(not(feature = "std"), no_std)]
223#![warn(missing_docs)]
224#![warn(clippy::missing_safety_doc)]
225#![warn(clippy::undocumented_unsafe_blocks)]
226
227// ============================================================================
228// EXTERNAL DEPENDENCIES
229// ============================================================================
230
231#[cfg(not(feature = "std"))]
232extern crate alloc;
233
234// ============================================================================
235// COMPILE-TIME FEATURE VALIDATION
236// ============================================================================
237
238// Improved feature validation that allows testing with --all-features
239// but warns about suboptimal configurations
240
241#[cfg(all(
242    feature = "fast",
243    feature = "secure",
244    not(test),  // Allow all features during testing
245    not(doc),
246    not(debug_assertions),
247))]
248compile_error!("Both 'fast' and 'secure' features are enabled. For optimal performance, choose only 'fast'. For security, choose only 'secure'.");
249
250#[cfg(all(
251    feature = "fast",
252    feature = "crypto",
253    not(test),  // Allow all features during testing
254    not(doc),
255    not(debug_assertions),
256))]
257compile_error!("Both 'fast' and 'crypto' features are enabled. For optimal performance, choose only 'fast'. For cryptographic security, choose only 'crypto'.");
258
259#[cfg(all(
260    feature = "secure",
261    feature = "crypto",
262    not(test),  // Allow all features during testing
263    not(doc),
264    not(debug_assertions),
265))]
266compile_error!("Both 'secure' and 'crypto' features are enabled. Choose one hash algorithm based on your security requirements.");
267
268// ============================================================================
269// INTERNAL MODULES
270// ============================================================================
271
272pub mod domain;
273pub mod error;
274pub mod id;
275pub mod key;
276pub mod utils;
277pub mod validation;
278
279#[cfg(feature = "uuid")]
280pub mod uuid;
281
282// IMPORTANT: Macros module must be declared but not re-exported with pub use
283// because macros are automatically exported with #[macro_export]
284#[macro_use]
285mod macros;
286
287// ============================================================================
288// PUBLIC RE-EXPORTS
289// ============================================================================
290
291// Core types
292#[cfg(feature = "uuid")]
293pub use domain::UuidDomain;
294pub use domain::{
295    domain_info, DefaultDomain, Domain, DomainInfo, IdDomain, IdentifierDomain, KeyDomain,
296    PathDomain,
297};
298#[cfg(feature = "uuid")]
299pub use error::UuidParseError;
300pub use error::{ErrorCategory, IdParseError, KeyParseError};
301pub use id::Id;
302pub use key::Key;
303#[cfg(feature = "uuid")]
304pub use uuid::Uuid;
305
306// Helper types
307pub use key::{KeyValidationInfo, SplitCache, SplitIterator};
308pub use validation::IntoKey;
309
310// Utility functions
311pub use utils::{hash_algorithm, new_split_cache};
312pub use validation::*;
313
314// Constants
315pub use key::DEFAULT_MAX_KEY_LENGTH;
316
317// Hidden re-exports for macro hygiene (so macros work without caller imports)
318#[doc(hidden)]
319pub mod __private {
320    #[cfg(not(feature = "std"))]
321    pub use alloc::string::ToString;
322    #[cfg(feature = "std")]
323    pub use std::string::ToString;
324
325    #[cfg(not(feature = "std"))]
326    pub use alloc::vec::Vec;
327    #[cfg(feature = "std")]
328    pub use std::vec::Vec;
329}
330
331// Note: Macros are exported automatically by #[macro_export] in macros.rs
332// They don't need to be re-exported here
333
334// ============================================================================
335// CONVENIENCE TYPE ALIASES
336// ============================================================================
337
338/// Result type for key operations
339pub type KeyResult<T> = Result<T, KeyParseError>;
340
341// ============================================================================
342// PRELUDE MODULE
343// ============================================================================
344
345/// Prelude module for convenient imports
346///
347/// This module re-exports the most commonly used types and traits, allowing
348/// users to easily import everything they need with a single `use` statement.
349///
350/// # Examples
351///
352/// ```rust
353/// use domain_key::prelude::*;
354///
355/// #[derive(Debug)]
356/// struct MyDomain;
357///
358/// impl Domain for MyDomain {
359///     const DOMAIN_NAME: &'static str = "my";
360/// }
361/// impl KeyDomain for MyDomain {}
362///
363/// type MyKey = Key<MyDomain>;
364///
365/// let key = MyKey::new("example")?;
366/// # Ok::<(), KeyParseError>(())
367/// ```
368pub mod prelude {
369    pub use crate::{
370        Domain, DomainInfo, ErrorCategory, Id, IdDomain, IdParseError, IntoKey, Key, KeyDomain,
371        KeyParseError, KeyResult, KeyValidationInfo,
372    };
373
374    #[cfg(feature = "uuid")]
375    pub use crate::{Uuid, UuidDomain, UuidParseError};
376
377    // Re-export the macros in prelude for convenience
378    // Note: These are already available at crate root due to #[macro_export]
379    // but users might want them in prelude
380    #[doc(hidden)]
381    pub use crate::{
382        batch_keys, define_domain, define_id, define_id_domain, id_type, key_type, static_key,
383        test_domain,
384    };
385
386    #[cfg(feature = "uuid")]
387    #[doc(hidden)]
388    pub use crate::{define_uuid, define_uuid_domain, uuid_type};
389}