# `variant_builder_macro`
A procedural macro to simplify the creation of builder methods for enum variants, especially when used with the [`derive_builder`](https://crates.io/crates/derive_builder) crate. This macro automates the generation of variant-specific builder methods, enabling concise and flexible creation of enum instances.
---
## Features
- **Automated Builder Methods**: Automatically generates builder methods for each variant in an enum.
- **Integration with `derive_builder`**: Works seamlessly with the `derive_builder` crate to manage complex field initialization.
- **Default Variant Support**: Automatically implements the `Default` trait for enums with a designated `#[default]` variant.
- **Improved Type Safety**: Ensures that only valid builder configurations are allowed.
- **Simplified API**: Reduces boilerplate by eliminating the need to manually write repetitive constructor methods.
---
## Installation
Add `variant_builder_macro` to your `Cargo.toml`:
```toml
[dependencies]
variant_builder_macro = "0.1"
derive_builder = "0.10" # Required for field builders
```
---
## Usage
### Basic Example
Define an enum and apply the `VariantBuilder` macro. Each variant must have a single unnamed field with a type that implements `Default` and has a builder (e.g., generated by `derive_builder`). Use the `#[default]` attribute to specify a default variant.
```rust
use variant_builder_macro::VariantBuilder;
use derive_builder::Builder;
#[derive(VariantBuilder, Debug, Clone, PartialEq)]
pub enum AnimalVenom {
#[default]
Contact(ContactVenom),
Injected(InjectedVenom),
Defensive(DefensiveVenom),
Offensive(OffensiveVenom),
}
#[derive(Builder, Debug, Clone, PartialEq, Default)]
#[builder(setter(into))]
pub struct ContactVenom {
potency: String,
activation: String,
}
#[derive(Builder, Debug, Clone, PartialEq, Default)]
#[builder(setter(into))]
pub struct InjectedVenom {
delivery_method: String,
potency: String,
}
#[derive(Builder, Debug, Clone, PartialEq, Default)]
#[builder(setter(into))]
pub struct DefensiveVenom {
deterrence: String,
effectiveness: u32,
}
#[derive(Builder, Debug, Clone, PartialEq, Default)]
#[builder(setter(into))]
pub struct OffensiveVenom {
speed: u32,
potency: String,
}
```
### Generated API
The macro generates builder methods for each variant. For example, for the `Contact` variant:
```rust
impl AnimalVenom {
pub fn contact<F>(build: F) -> Self
where
F: FnOnce(&mut ContactVenomBuilder),
{
let mut builder = ContactVenomBuilder::default();
build(&mut builder);
Self::Contact(builder.build().expect("Builder failed to construct variant"))
}
}
```
Additionally, if a `#[default]` attribute is specified, the `Default` trait is implemented automatically:
```rust
impl Default for AnimalVenom {
fn default() -> Self {
Self::Contact(Default::default())
}
}
```
---
### Examples
#### Creating Enum Variants with Builders
```rust
fn main() {
let contact_venom = AnimalVenom::contact(|builder| {
builder
.potency("High".to_string())
.activation("Immediate".to_string());
});
let injected_venom = AnimalVenom::injected(|builder| {
builder
.delivery_method("Spines".to_string())
.potency("Moderate".to_string());
});
println!("{:?}", contact_venom);
println!("{:?}", injected_venom);
}
```
#### Using Default Values
If no fields are modified, the builder uses default values. The default variant is used for `Default::default()`:
```rust
let default_contact_venom = AnimalVenom::default();
println!("{:?}", default_contact_venom);
```
You can also explicitly call the default variant builder:
```rust
## Testing
This crate includes a comprehensive test suite. Run the tests with:
```bash
cargo test
```
---
## Limitations
- Each variant must have exactly one unnamed field.
- The field type must implement `Default` and provide a `build` method (e.g., via `derive_builder`).
- Only one variant can be marked with `#[default]`.
---
## License
This crate is licensed under the MIT License. See [LICENSE](./LICENSE) for details.
---
## Contributions
Contributions are welcome! If you find any issues or have ideas for new features, feel free to open an issue or submit a pull request.