Open wackazong opened 1 year ago
My use case would be to allow for the control of default values for keys and timestamps in different testing environments.
To keep the
builder()
function as is, there could be a.context()
function to set the context.
So... something like this?
#[derive(TypedBuilder)]
#[builder(context(/*Syntax TBD*/))]
struct Foo {
#[buidler(default = self.context())]
bar: i32,
}
// This will work:
Foo::builder().context(Context::new()).build();
// This will work:
Foo::builder().bar(42).build();
// This will not:
Foo::builder().build();
This can be a bit hard to model, but what if we require the context to always have a default?
Also, rather than a "context" method, I'd rather do something ike this:
#[derive(TypedBuilder)]
#[builder(context(
// Will be treated like a field that does not get into the final struct
number: i32 = 4,
))]
struct Foo {
#[buidler(default = number * 10 + 2)]
bar: i32,
}
Yes, the first proposition would be great. The context would just need to be available in the builder, not in the final struct. I would like to set the context at runtime, therefore an attribute macro as you suggested would not serve me.
Maybe like this?
struct Context;
impl Context {
fn bar() {
...
}
}
#[derive(TypedBuilder)]
struct Foo {
#[builder(use_context_for_default)]
bar: i32,
}
// if a field is marked with use_context_for_default then a context needs to be supplied
// and the default value is derived from the context passed in at runtime
// context will be required for each call of builder if default value is not given
Foo::builder().context(Context::new()).build();
// This will work:
Foo::builder().bar(42).build();
// This will not:
Foo::builder().build();
I really don't want to move the defaults elsewhere. If I have to specify dependencies, I'd rather make a breaking change and do something like this:
#[derive(TypedBuilder)]
#[builder(context(
x: i32 = 1,
y: i32 = 2,
))]
struct MyStruct {
// Depends only on `x`
#[buidler(default = |x| x + 1)]
foo: i32,
// Depends only on `y`
#[buidler(default = |y| y + 2)]
bar: i32,
// Depends on both
#[buidler(default = |x, y| x + y + 3)]
baz: i32,
// Depends on nothing
#[buidler(default = || 4)]
baz: i32,
}
But... I really don't want to jump into the complexities of these dependencies, and I think that if it's just for the context fields I can get a way with using default values.
For me the most important would be to pass in the context at runtime and not at compile time.
I would love to see a feature that allows to set a context for the builder. The context could then be used in the default functions. To keep the
builder()
function as is, there could be a.context()
function to set the context. Then we could use something like::#[builder(default_code = "self.context()")]
What do you think?
I find the code of this crate quite complex for me as a Rust beginner, but I would be happy to do a PR if given some pointers on where to start.