Optional members
Setters generated for members of Option<T> type are themselves optional to call. If they aren't invoked, then None will be used as the default.
Example:
use bon::builder;
#[builder]
fn example(level: Option<u32>) {}
// We can call it without specifying `level`
example().call();The setters generated in the example above are the following (simplified):
impl ExampleBuilder {
// Accepts the underlying value. Wraps it in `Some()` internally
fn level(value: u32) -> NextBuilderState { /* */ }
// Accepts the `Option` directly.
fn maybe_level(value: Option<u32>) -> NextBuilderState { /* */ }
}This allows for the following call patterns.
If you need to pass a simple literal value, then the syntax is very short
example().level(42).call();If you already have an Option variable somewhere or you need to dynamically decide if the value should be Some or None, then you can use the maybe_ variant of the setter.
let value = if some_condition {
Some(42)
} else {
None
};
example().maybe_level(value).call();To make a non-Option function argument or struct field optional you may add #[builder(default)] to it, which generates the equivalent builder API as if the type was Option<T>. See #[builder(default)] docs for details.
Interaction with Into conversions
The inner type T of the Option<T> is subject to Into conversion. For example, if T by default qualifies for an automatic Into conversion or #[builder(into)] was used to force it, then the generated builder API will provide the following two setters:
impl Builder {
fn member(self, value: impl Into<T>) -> NextBuilderState { /* */ }
fn maybe_member(self, value: Option<impl Into<T>>) -> NextBuilderState { /* */ }
}Example:
use bon::builder;
#[builder]
fn example(level: Option<String>) {}
example()
.level("Accepts `impl Into<String>`, which allows for passing `&str`")
.call();
example()
.maybe_level(Some(
"Accepts `Option<impl Into<String>>`, \
which allows for passing `Option<&str>`"
))
.call();