rust-typed-builder
rust-typed-builder copied to clipboard
Setter taking `Option` for non-optional fields
I have a a value coming from clap argument parsing that might or might not be set (so it's Option<u64>, and I want to use it (if set) to override a field that has a default in typed-builder for Params.
Ideally I'd like to:
let params = Parameters::builder()
.db_path(opts.db_path.clone())
.base_segment_file_size(opts.segment_size)
.build();
but this doesn't work because opts.segment_size is Option<u64> and base_segment_file_size: u64.
Trying to achieve it with an if statement doesn't work either, because the type of each branch are different, and there seem to be no way to get the default value.
This would work:
let params = if let Some(segment_size) = opts.base_segment_file_size {
params.base_segment_file_size(segment_size)
} else {
params.base_segment_file_size(/* how to get the default? */)
};
if there was a way to actually get the default defined in #[builder(default = 16 * 1024 * 1024)].
I eventually moved the default into separate constant and went with:
let params = if let Some(segment_size) = opts.base_segment_file_size {
params.base_segment_file_size(segment_size)
} else {
params.base_segment_file_size(Parameters::DEFAULT_BASE_SEGMENT_SIZE)
};
Maybe I can add a #[builder(setter(explicit_default))] option, that will make the field mandatory even if it has a default (I'll force it to have a default), but make the setter accept and Option and set it to the default if it receives a None?
As a side note - why are you using TypedBuilder to pass fields from clap a Parameters struct instead of making Parameters a #[derive(Parser)] and using #[clap(flatten)] to embed it in your main clap parser?
Maybe I can add a
#[builder(setter(explicit_default))]option, that will make the field mandatory even if it has a default (I'll force it to have a default), but make the setter accept andOptionand set it to the default if it receives aNone?
I'm not entirely clear here on the details, but merging behavior (None argument just doesn't change the underlying value) is kind of preferable, IMO. In my use case this doesn't matter however.
As a side note - why are you using
TypedBuilderto pass fields from clap aParametersstruct instead of makingParametersa#[derive(Parser)]and using#[clap(flatten)]to embed it in your main clap parser?
I am not sure what do you mean exactly, so it didn't even cross my mind. But that TypedBuilder is more generic and meant for library consumption, and the clap exposes only some of the values to override, and they could even eventually live in different crates.