idanarye / rust-typed-builder

Compile-time type-checked builder derive
https://crates.io/crates/typed-builder
Apache License 2.0
904 stars 52 forks source link

Manage compute fields struct #148

Closed natir closed 2 months ago

natir commented 2 months ago

Hello,

I've tried to find a workaround to do what I want to do but I haven't found a pleasant solution.

I have a struct where a certain number of fields are calculated from others.

#[derive([typed_builder::TypedBuilder))]
struct Foo {
    x: usize,,
    y: usize,
    z: usize, // z should be the sum of x and y 
}

Via the default field I can integrate this calculation but the user can overwrite the results of this computation by use setter.

#[derive([typed_builder::TypedBuilder))]
struct Foo {
    x: usize,,
    y: usize,
    #[builder(default = x + y)]
    z: usize, 
}

let bar = Foo::builder.x(1).y(5).z(12)
assert_eq!(
    bar,
    Foo{
        x: 1,
        y: 5,
       z: 12 // z should be 6
});

A solution would be to replace the build method to rewrite the user's modifications, but this solution duplicate code.

I thought I'd found a solution via mutators, but if the methods aren't called by the user, the values aren't initialized. (maybe I miss something)

One solution would be to add to builder an attribute compute execute during build call but doesn't expose a setter. Or an attribute ignore to not let user set value and then use the build method replacement to compute value.

I tried to find similar issues but may have missed it, if so I'm sorry. I also understand that my request is too far from the scope of the library.

idanarye commented 2 months ago

This is already supported with setter(skip):

#[derive(typed_builder::TypedBuilder)]
struct Foo {
    x: usize,
    y: usize,
    #[builder(setter(skip), default = x + y)]
    z: usize, 
}
natir commented 2 months ago

Sorry ! …