Crates.io | variant-builder-macro |
lib.rs | variant-builder-macro |
version | 0.2.0 |
source | src |
created_at | 2024-12-06 07:49:15.234213 |
updated_at | 2024-12-06 08:09:22.906903 |
description | This crate gives us the VariantBuider proc macro which can be used to streamline creting an enum from wrapping variants each using the builder pattern. |
homepage | |
repository | https://github.com/klebs6/klebs-general |
max_upload_size | |
id | 1474017 |
size | 13,924 |
variant_builder_macro
A procedural macro to simplify the creation of builder methods for enum variants, especially when used with the derive_builder
crate. This macro automates the generation of variant-specific builder methods, enabling concise and flexible creation of enum instances.
derive_builder
: Works seamlessly with the derive_builder
crate to manage complex field initialization.Default
trait for enums with a designated #[default]
variant.Add variant_builder_macro
to your Cargo.toml
:
[dependencies]
variant_builder_macro = "0.1"
derive_builder = "0.10" # Required for field builders
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.
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,
}
The macro generates builder methods for each variant. For example, for the Contact
variant:
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:
impl Default for AnimalVenom {
fn default() -> Self {
Self::Contact(Default::default())
}
}
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);
}
If no fields are modified, the builder uses default values. The default variant is used for Default::default()
:
let default_contact_venom = AnimalVenom::default();
println!("{:?}", default_contact_venom);
You can also explicitly call the default variant builder:
let default_contact_venom = AnimalVenom::contact(|_builder| {});
println!("{:?}", default_contact_venom);
You can initialize only the fields you need:
let defensive_venom = AnimalVenom::defensive(|builder| {
builder.deterrence("High".to_string());
});
println!("{:?}", defensive_venom);
This crate includes a comprehensive test suite. Run the tests with:
cargo test
Default
and provide a build
method (e.g., via derive_builder
).#[default]
.This crate is licensed under the MIT License. See LICENSE for details.
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.