nestum 0.1.4

Proc-macro for nested enum paths like Enum1::Variant1::VariantA
Documentation

nestum

nestum makes nested enum paths and matches feel natural, so you can codify invariants by nesting related enums while keeping ergonomic construction and matching.

use nestum::{nestum, nested};

#[derive(Debug)]
pub struct Document {
    pub id: String,
}

#[derive(Debug)]
pub struct Image {
    pub id: String,
}

#[nestum]
pub enum DocumentsEvent {
    Update(Document),
    Delete(String),
}

#[nestum]
pub enum ImagesEvent {
    Update(Image),
    Delete(String),
}

#[nestum]
pub enum Event {
    Documents(DocumentsEvent),
    Images(ImagesEvent),
}

let event = Event::Documents::Update(Document { id: "doc-1".to_string() });
nested! {
    match event {
        Event::Documents::Update(doc) => {
            let _ = doc.id;
        }
        Event::Documents::Delete(id) => {
            let _ = id;
        }
        Event::Images::Update(img) => {
            let _ = img.id;
        }
        Event::Images::Delete(id) => {
            let _ = id;
        }
    }
}

Instead of:

Event::Documents(DocumentsEvent::Update(doc))

you can write:

Event::Documents::Update(doc)

Where this pays off:

  • Event routing and message buses.
  • Permission or policy trees (resource + action).
  • Parsers/compilers (node + kind).
  • UIs with nested state machines.

The point is to encode invariants as nested enums (this variant always contains this family of sub-variants) without paying a readability or ergonomics tax when constructing or matching.

How To Use

use nestum::nestum;

#[derive(Debug)]
pub struct Document {
    pub id: String,
}

#[derive(Debug)]
pub struct Image {
    pub id: String,
}

#[nestum]
pub enum DocumentsEvent {
    Update(Document),
    Delete(String),
}

#[nestum]
pub enum ImagesEvent {
    Update(Image),
    Delete(String),
}

#[nestum]
pub enum Event {
    Documents(DocumentsEvent),
    Images(ImagesEvent),
}

fn main() {
    let doc = Document { id: "doc-1".to_string() };
    let _ = Event::Documents::Update(doc);
    let _ = Event::Images::Delete("img-1".to_string());
}

Cross-Module Nesting

To nest an enum declared in a different module file, use an external path on the variant:

use nestum::nestum;

mod inner;

#[nestum]
pub enum Outer {
    #[nestum(external = "crate::inner::Inner")]
    Wrap(Inner),
}

fn main() {
let _ = Outer::Wrap::A;
}

API Summary

#[nestum] on enums

Enables nested paths and match rewriting.

#[nestum(external = "path::to::Enum")] on variants

Opt-in support for nesting an enum in another module file.

nestum_match! { match value { ... } } / nested! { match value { ... } }

Macro that rewrites nested patterns (like Event::Documents::Update) into real enum patterns.

Limitations

  • External crates are not supported (proc macros can’t reliably inspect other crates’ ASTs).
  • The macro only resolves enums from source files in the current crate.
  • #[path = "..."], include!(), and complex cfg layouts may not be resolved.

License

MIT