# `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(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 let default_contact_venom = AnimalVenom::contact(|_builder| {}); println!("{:?}", default_contact_venom); ``` #### Partial Field Initialization You can initialize only the fields you need: ```rust let defensive_venom = AnimalVenom::defensive(|builder| { builder.deterrence("High".to_string()); }); println!("{:?}", defensive_venom); ``` --- ## 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.