Nestum
Construct:
Created
instead of:
Document
and match the same way with nested!.
use ;
let inner: Enum = Created;
let event: Enum = Created;
nested!
let _ = inner;
Mental Model
#[nestum]on an enum turns the enum name into a namespace for nested-path constructors.nested! { ... }rewrites nested constructors and nested patterns where Rust syntax needs help.#[nestum_scope]rewrites a whole function, impl, method, or inline module body so you do not need as many localnested!wrappers.- If you need the concrete enum type itself, use
Outer::Enum<T>.
That namespace tradeoff is what makes Event::Document::Created possible in ordinary Rust syntax.
What This Path Means
DocumentEvent::Createdconstructs aDocumentEvent::Enum.Event::Document::Createdconstructs anEvent::Enum.Event::Documentis a namespace branch, not a completedEventvalue.
Good fits for nestum look like:
Event::Document::CreatedCommand::User::CreateMessage::Billing::Paid
Weak fits usually look like:
- a one-off wrapper where helper functions already hide the wrapping noise
- a hierarchy you would have to invent just to get prettier syntax
- names like
Document::Event::Createdthat read like inner type namespaces instead of outer envelope values
nestum is strongest when the outer enum is already a real envelope over event, command, or message families.
Quick Start
- Add
#[nestum]to each enum in the hierarchy. - Construct wrapped values with nested paths like
Event::Document::Created. - Use
nested! { ... }for focused rewrites, or put#[nestum_scope]on the enclosing function, impl, method, or inline module to rewrite a wider scope at once.
Real-World Showcases
The nestum-examples workspace crate shows the macro against real libraries instead of toy enums.
todo_api: Axum + in-memory SQLite + broadcast events. This proves nested command trees, nested domain errors, and nested events can survive a normal web stack.ops_cli: Clap subcommands with nested dispatch. This proves nestum can sit on top of derive-heavy command surfaces without turning the type tree into boilerplate.
Run them with:
Coding Agents
If you use coding agents, see docs/agents/. It includes copyable instruction templates, an opportunity-signals guide, an audit playbook, and prompts for audits, greenfield design, review, and targeted refactors.
Examples
Basic Nesting
let _ = Created;
let _ = Archived;
Named-Field Constructors
Use nested! when the nested leaf is a named-field variant:
use ;
let value: Enum = nested! ;
Scope-Level Rewriting
Use #[nestum_scope] when a function or impl body has several nested constructors or patterns:
use ;
Cross-Module Nesting
Use #[nestum(external = "...")] when the inner enum lives in another module file:
let _ = A;
Ecosystem Compatibility
nestum still works with common derive-heavy Rust crates. The test suite covers:
serderound trips for wrapped outer enumsthiserrorderives with transparent outer error envelopes- common assertion macros, including
assert!(matches!(...))
Core Rules
- Only enums are supported.
- Both the outer enum and the nested inner enum need
#[nestum]. - Use
nested!for focused rewrites, or#[nestum_scope]for function-, impl-, method-, or inline-module-level rewrites.
Advanced Notes
- In type positions, use
Outer::Enum<T>for the enum type itself. - Put
#[nestum]before#[derive(...)]so derive macros see the rewritten enum shape. serde,thiserror, and common assertion macros are covered by tests.- Generic outer enums use functions for unit constructors, so
Outer::Other()orOuter::Wrap::Ready()may be function calls instead of constants. - Plain local inner enum paths,
self::...,super::..., and qualified crate-local inner enum paths are supported, including generic arguments. - Cross-module nesting is explicit with
#[nestum(external = "crate::path::Enum")]. - For nested variants, the raw root constructor path like
Outer::Wrap(inner)is no longer part of the public surface; useOuter::Enum::Wrap(inner)if you need the explicit underlying constructor. #[nestum_scope]rewrites normal Rust AST inside the annotated item body and also handlesmatches!,assert!,debug_assert!,assert_eq!,assert_ne!, and their debug variants.
Limitations
- Most other outer macro token trees are still opaque to
#[nestum_scope]. - qself or associated paths are rejected for nested field detection.
#[path = "..."],include!(), and complexcfgmodule layouts may not resolve.- External crates are not supported because proc macros cannot reliably inspect dependency sources.
API
#[nestum]
Marks an enum so nested enum-wrapping variants can be constructed through path-shaped syntax.
use nestum;
let _ = A;
nested! { ... }
Rewrites nested constructors and nested patterns into ordinary Rust enum syntax.
Use it for match, if let, while let, let-else, matches!, common assertion macros, and named-field nested construction.
use ;
let value = B;
let ok = nested! ;
#[nestum_scope]
Rewrites nested constructors and nested patterns across a wider body.
Use it on functions, impl methods, impl blocks, or inline modules when local nested! wrappers would get noisy.
use ;
#[nestum(external = "path::to::Enum")]
Marks a variant as wrapping a nested enum defined in another module file.
use nestum;
nestum_match! { match value { ... } }
Match-only compatibility macro. Prefer nested! unless you specifically want a match-only entry point.
License
MIT