-
-
Notifications
You must be signed in to change notification settings - Fork 37
Closed
Description
The following shows a macro I use heavily in my code to mostly remove the need to call the finish fn.
macro_rules! builder_to_built_impl {
($name:ident) => {
paste::paste! {
impl<S: [<$name:snake _builder>]::State + [<$name:snake _builder>]::IsComplete> From<[<$name Builder>]<S>> for $name {
fn from(value: [<$name Builder>]<S>) -> Self {
value.call()
}
}
}
};
}
struct Foo {
bar: Option<u32>,
bazz: bool,
}
#[bon::builder]
fn foo(bar: Option<u32>, bazz: bool) -> Foo {
Foo { bar, bazz }
}
builder_to_built_impl!(Foo);
fn test(foo: impl Into<Foo>) {}
fn main() {
test(foo().bazz(false).call());
test(foo().bazz(true)); // call not required
// one can now just call `into` instead of `call`
let test1: Foo = foo().bazz(true).into();
// `into` is better than calling `call`, as we can support more than just builders
macro_rules! foos {
($($foo:expr),* $(,)?) => {
vec![$($foo.into(),)*]
};
}
let foos: Vec<Foo> = foos![foo().bazz(true), foo().bazz(false)];
}I believe this could be better handled by bon directly, as it knows the name of the top-level finish_fn (call in this case). This of course can't be used when a member-level finish_fn is used, since Into can't take arguments.
The proposed syntax change would be:
#[bon::builder(into)]
fn foo(bar: Option<u32>, bazz: bool) -> Foo {
Foo { bar, bazz }
}Which would generate:
impl<S: foo_builder::State + foo_builder::IsComplete> From<FooBuilder<S>> for Foo {
fn from(value: FooBuilder<S>) -> Self {
value.call()
}
}Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels