Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Special Setter/Initializer #142

Open
taooceros opened this issue Apr 23, 2024 · 2 comments
Open

Special Setter/Initializer #142

taooceros opened this issue Apr 23, 2024 · 2 comments

Comments

@taooceros
Copy link

Is it possible to customize a setter for initializing a couple of fields? For example, I want the builder being able to accept a different struct that contains some information about some fields.

This is possible with mutator, but that will get rid of the compile time checking of those fields, which I do want the builder to be able to detect whether that setter is called.

Thanks for the very cool project!

@taooceros taooceros changed the title Special Setter Special Setter/Initializer Apr 23, 2024
@idanarye
Copy link
Owner

How would it looks like? Something like this?

#[derive(TypedBuilder)]
#[builder(setters(
        #[setter(sets = (bar, baz))]
        fn bar_and_baz(&self, bar: i32, baz: i32) -> (i32, i32) {
            (bar, baz)
        }
))]
struct Foo {
    bar: i32,
    baz: i32,
}

@fMeow
Copy link
Contributor

fMeow commented Apr 28, 2024

This is possible outside of macros provided by typed-builder, which means we have to write some hacky generic. But it's fine with the help of cargo expand subcommand.

Say we have the following struct:

#[derive(TypedBuilder)]
struct Foo {
    bar: i32,
    baz: f64,
    qux: i16
}

With cargo expand, we can see the generated builder and helper by typed-builder. Here is the generated builder function for qux field:

#[allow(dead_code, non_camel_case_types, missing_docs)]
#[automatically_derived]
impl<__bar, __baz> FooBuilder<(__bar, __baz, ())> {
    #[allow(clippy::used_underscore_binding, clippy::no_effect_underscore_binding)]
    pub fn qux(self, qux: i16) -> FooBuilder<(__bar, __baz, (i16,))> {
        let qux = (qux,);
        let (bar, baz, ()) = self.fields;
        FooBuilder {
            fields: (bar, baz, qux),
            phantom: self.phantom,
        }
    }
}

So we can create our own functions, based on the above code from cargo expand. Here is a hand written setter for setting bar and baz at once:

#[allow(dead_code, non_camel_case_types, missing_docs)]
#[automatically_derived]
impl<__qux> FooBuilder<((), (), __qux)> {
    #[allow(clippy::used_underscore_binding, clippy::no_effect_underscore_binding)]
    // function signature is fully customizible, like function name, params.
    pub fn bar_and_baz(self, bar:i32, baz: f64) -> FooBuilder<((i32,), (f64,), __qux)> {
        let baz = (baz,);
        let bar = (bar,)
        let ((), (), qux) = self.fields;
        FooBuilder {
            fields: (bar, baz, qux),
            phantom: self.phantom,
        }
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants