#[cfg(not(all(feature = "doc-gen", feature = "auto-register")))]
compile_error!(
"This example requires the 'doc-gen' and 'auto-register' features.\n\
Run with: cargo run --example multiple_namespaces --features \"doc-gen,auto-register\""
);
#[cfg(all(feature = "doc-gen", feature = "auto-register"))]
use waddling_errors_macros::setup;
#[cfg(all(feature = "doc-gen", feature = "auto-register"))]
pub mod components {
use waddling_errors_macros::component;
component! {
Auth {
docs: "Authentication and authorization system",
tags: ["security", "authentication"],
},
Payment {
docs: "Payment processing system",
tags: ["payment", "billing"],
},
Core {
docs: "Core system functionality",
tags: ["core", "system"],
},
}
}
#[cfg(all(feature = "doc-gen", feature = "auto-register"))]
pub mod primaries {
use waddling_errors_macros::primary;
primary! {
pub enum Primary {
Token {
description: "Authentication token errors",
},
Card {
description: "Credit card errors",
},
Init {
description: "Initialization errors",
},
}
}
}
#[cfg(all(feature = "doc-gen", feature = "auto-register"))]
pub mod sequences {
use waddling_errors_macros::sequence;
sequence! {
EXPIRED(17) {
description: "Token or resource has expired",
},
INVALID(3) {
description: "Validation failed",
},
DECLINED(51) {
description: "Request was declined",
},
FAILED(99) {
description: "Operation failed",
},
}
}
#[cfg(all(feature = "doc-gen", feature = "auto-register"))]
setup! {
components = crate::components,
primaries = crate::primaries,
sequences = crate::sequences,
}
#[cfg(all(feature = "doc-gen", feature = "auto-register"))]
mod auth_errors {
use waddling_errors_macros::diag;
diag! {
namespace: "auth_service",
strict(component, primary, sequence, naming, duplicates, sequence_values, string_values),
<json>,
E.Auth.Token.EXPIRED: {
message: "Authentication token has expired",
fields: [token_id],
},
E.Auth.Token.INVALID: {
message: "Authentication token is invalid",
fields: [token_id, reason],
},
}
}
#[cfg(all(feature = "doc-gen", feature = "auto-register"))]
mod payment_errors {
use waddling_errors_macros::diag;
diag! {
namespace: "payment_service",
strict(component, primary, sequence, naming, duplicates, sequence_values, string_values),
<json>,
E.Payment.Card.DECLINED: {
message: "Credit card was declined",
fields: [card_last_four, decline_reason],
},
E.Payment.Card.EXPIRED: {
message: "Credit card has expired",
fields: [card_last_four, expiry_date],
},
}
}
#[cfg(all(feature = "doc-gen", feature = "auto-register"))]
mod core_errors {
use waddling_errors_macros::diag;
diag! {
strict(component, primary, sequence, naming, duplicates, sequence_values, string_values),
<json>,
E.Core.Init.FAILED: {
message: "Core system initialization failed",
fields: [subsystem, error_code],
},
}
}
#[cfg(all(feature = "doc-gen", feature = "auto-register"))]
fn main() {
println!("=== Multiple Namespace Example ===\n");
println!("--- Auth Service Namespace ---");
println!("E_AUTH_TOKEN_EXPIRED:");
println!(" Code: {}", auth_errors::E_AUTH_TOKEN_EXPIRED.code);
println!(
" Namespace: {:?}",
auth_errors::E_AUTH_TOKEN_EXPIRED.namespace
);
println!(
" Namespace Hash: {:?}",
auth_errors::E_AUTH_TOKEN_EXPIRED.namespace_hash
);
println!();
println!("E_AUTH_TOKEN_INVALID:");
println!(" Code: {}", auth_errors::E_AUTH_TOKEN_INVALID.code);
println!(
" Namespace: {:?}",
auth_errors::E_AUTH_TOKEN_INVALID.namespace
);
println!(
" Namespace Hash: {:?}",
auth_errors::E_AUTH_TOKEN_INVALID.namespace_hash
);
println!();
println!("--- Payment Service Namespace ---");
println!("E_PAYMENT_CARD_DECLINED:");
println!(" Code: {}", payment_errors::E_PAYMENT_CARD_DECLINED.code);
println!(
" Namespace: {:?}",
payment_errors::E_PAYMENT_CARD_DECLINED.namespace
);
println!(
" Namespace Hash: {:?}",
payment_errors::E_PAYMENT_CARD_DECLINED.namespace_hash
);
println!();
println!("E_PAYMENT_CARD_EXPIRED:");
println!(" Code: {}", payment_errors::E_PAYMENT_CARD_EXPIRED.code);
println!(
" Namespace: {:?}",
payment_errors::E_PAYMENT_CARD_EXPIRED.namespace
);
println!(
" Namespace Hash: {:?}",
payment_errors::E_PAYMENT_CARD_EXPIRED.namespace_hash
);
println!();
println!("--- No Namespace (Global) ---");
println!("E_CORE_INIT_FAILED:");
println!(" Code: {}", core_errors::E_CORE_INIT_FAILED.code);
println!(
" Namespace: {:?}",
core_errors::E_CORE_INIT_FAILED.namespace
);
println!(
" Namespace Hash: {:?}",
core_errors::E_CORE_INIT_FAILED.namespace_hash
);
println!();
println!("=== Summary ===");
println!("Unique namespaces detected:");
println!(" 1. 'auth_service' - 2 errors");
println!(" 2. 'payment_service' - 2 errors");
println!(" 3. None (global) - 1 error");
println!();
println!("This would generate 3 separate catalogs when using doc-gen.");
println!("\n=== Namespace Hash Consistency ===");
let auth_ns_hash_1 = auth_errors::E_AUTH_TOKEN_EXPIRED.namespace_hash;
let auth_ns_hash_2 = auth_errors::E_AUTH_TOKEN_INVALID.namespace_hash;
println!(
"Auth service namespace hashes match: {}",
auth_ns_hash_1 == auth_ns_hash_2
);
let payment_ns_hash_1 = payment_errors::E_PAYMENT_CARD_DECLINED.namespace_hash;
let payment_ns_hash_2 = payment_errors::E_PAYMENT_CARD_EXPIRED.namespace_hash;
println!(
"Payment service namespace hashes match: {}",
payment_ns_hash_1 == payment_ns_hash_2
);
println!(
"Auth vs Payment hashes differ: {}",
auth_ns_hash_1 != payment_ns_hash_1
);
println!("\n=== Global Registry (auto-registered via <json>) ===\n");
let diagnostics = waddling_errors::registry::get_diagnostics();
println!("Total registered diagnostics: {}", diagnostics.len());
println!("\nErrors by namespace:");
for reg in &diagnostics {
println!(
" - {} (namespace: {:?}, namespace_hash: {:?})",
reg.diagnostic.runtime.code,
reg.diagnostic.runtime.namespace,
reg.diagnostic.runtime.namespace_hash
);
}
println!("\n=== Catalog Structure ===");
let mut by_namespace: std::collections::HashMap<Option<&str>, Vec<&str>> =
std::collections::HashMap::new();
for reg in &diagnostics {
by_namespace
.entry(reg.diagnostic.runtime.namespace)
.or_default()
.push(reg.diagnostic.runtime.code);
}
let mut catalog_count = 0;
for (namespace, codes) in &by_namespace {
catalog_count += 1;
match namespace {
Some(ns) => println!(
"Catalog {}: namespace '{}' ({} errors)",
catalog_count,
ns,
codes.len()
),
None => println!(
"Catalog {}: global/default ({} errors)",
catalog_count,
codes.len()
),
}
for code in codes {
println!(" - {}", code);
}
}
println!("\n=== Summary ===");
println!("Total catalogs that would be generated: {}", catalog_count);
println!("\n=== JSON Catalog Generation ===\n");
use waddling_errors::doc_generator::{DocRegistry, JsonRenderer};
let mut doc_registry = DocRegistry::new("MultiNamespaceDemo", "1.0.0");
waddling_errors::registry::register_all_with_doc_gen(&mut doc_registry);
println!(
"DocRegistry contains {} errors",
doc_registry.errors().len()
);
for (code, error) in doc_registry.errors() {
println!(" - {} (namespace: {:?})", code, error.namespace);
}
let output_dir = std::env::temp_dir().join("multiple_namespaces_output");
std::fs::create_dir_all(&output_dir).expect("Failed to create output dir");
doc_registry
.render(vec![Box::new(JsonRenderer)], &output_dir)
.expect("Failed to render JSON");
let json_path = output_dir.join("MultiNamespaceDemo.json");
let json_content = std::fs::read_to_string(&json_path).expect("Failed to read generated JSON");
println!("\n=== Generated JSON Catalog ===\n");
println!("{}", json_content);
println!("\n=== Output Location ===");
println!("JSON catalog written to: {}", json_path.display());
}
#[cfg(not(all(feature = "doc-gen", feature = "auto-register")))]
fn main() {}