# odin-union
`odin-union` provides a dependency-free attribute macro for declaring Rust
enums whose variants contain same-named types.
Instead of repeating each type:
```rust
enum Thing {
Person(Person),
Animal(Animal),
}
```
write:
```rust
use odin_union::odin_union;
struct Person {
name: String,
}
struct Animal {
species: String,
}
#[odin_union]
enum Thing {
Person,
Animal,
}
```
The macro expands the declaration to the ordinary payload enum above. It also
generates `From<Person> for Thing` and `From<Animal> for Thing`, so values can
be wrapped with `.into()`:
```rust
# use odin_union::odin_union;
# struct Person { name: String }
# struct Animal { species: String }
# #[odin_union]
# enum Thing { Person, Animal }
let person = Person {
name: "Ada".to_owned(),
};
let thing: Thing = person.into();
match thing {
Thing::Person(person) => assert_eq!(person.name, "Ada"),
Thing::Animal(_) => unreachable!(),
}
```
This is declaration shorthand, not a new runtime representation. The result is
a normal Rust enum: its tag and active payload are stored together, matching,
derives, visibility, and attributes continue to work normally, and no runtime
support library is involved.
## Rules
- Every listed variant must be a bare unit variant such as `Person`.
- A same-named type must be in scope at the enum declaration.
- The source enum cannot be generic. The macro cannot infer which generic
arguments should be supplied to each same-named payload type.
- A variant-level `#[cfg(...)]` attribute is copied to the generated `From`
implementation.
- Manually implementing the same `From<T>` conversion will conflict with the
generated implementation.
- Rust does not perform implicit user-defined conversions. Use `.into()`,
`Thing::from(value)`, or `Thing::Person(value)`.
The crate has no dependencies and supports Rust 1.85 or newer.