nestum 0.1.3

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.

Instead of:
```rust
Event::Documents(DocumentsEvent::Update(doc))
```

you can write:
```rust
Event::Documents::Update(doc)
```

The biggest win is matching:

```rust
nested! {
    match event {
        Event::Documents::Update(doc) => { /* ... */ }
        Event::Images::Delete(id) => { /* ... */ }
    }
}
```

It works by generating a shadow module hierarchy and wrapper constructors, plus a match macro that rewrites nested patterns.

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.

## Quick Start

```rust
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());
}
```

## Concepts

### Shadow module
When `#[nestum]` is applied to an enum, the macro replaces it with a module of the same name.
Inside that module, it re-emits the original enum and creates submodules for nested variants.
Those submodules expose wrapper constructors that build the outer enum.

This means the enum type itself is accessed as `EnumName::EnumName`.

### Nested variant detection
A variant is treated as nested **if and only if**:
- it is a tuple variant with exactly one field, and
- the inner field’s type is a simple enum ident that is also marked with `#[nestum]` in the same module.

This keeps nesting explicit without requiring per-variant annotations.

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

```rust
use nestum::nestum;

mod inner;

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

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

This resolves `crate::inner::Inner` to `src/inner.rs` or `src/inner/mod.rs` and generates wrappers.

## API Summary

### `#[nestum]` on enums
Enables shadow-module generation and wrapper constructors.

### `#[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 `Enum1::Variant1::VariantA`) into real enum patterns.

## Examples

### Basic nesting
```rust
#[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::Documents::Update(doc);
let _ = Event::Images::Delete("img-1".to_string());
```

### Cross-module nesting
```rust
mod inner;

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

let _ = Outer::Wrap::A;
```

### Nested match patterns (front and center)
```rust
use nestum::{nestum, nested};

#[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;
        }
    }
}
```

## 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.

## Error Messages
`nestum` emits detailed compile-time errors, including:
- invalid `#[nestum(...)]` usage,
- misuse on variants,
- external path mismatches,
- missing module files or enums.

## FAQ

### Why does the enum type become `EnumName::EnumName`?
Because `nestum` replaces the enum with a module of the same name. The original enum is re-emitted inside it.

### How do I pattern match with nested paths?
Use `nested!` (or `nestum_match!`) so paths like `Event::Documents::Update` are rewritten to the real enum pattern.

### Why not support external crates?
The macro would need to discover and parse dependency source files, which is brittle and not reliably possible in stable proc-macro APIs.

## License
MIT