### Short Syntax for `start_fn` Source: https://github.com/elastio/bon/blob/master/website/src/reference/builder/top-level/start_fn.md Use the short syntax to configure only the name of the starting function. This example renames the default `builder` function to `init`. ```rust use bon::Builder; #[derive(Builder)] #[builder(start_fn = init)] // [!code highlight] struct User { id: u32 } User::init() // [!code highlight] .id(42) .build(); ``` -------------------------------- ### Install Website Dependencies Source: https://github.com/elastio/bon/blob/master/website/README.md Run this command in the `website` directory to install the necessary project dependencies. ```bash npm install ``` -------------------------------- ### Install Benchmark Dependencies Source: https://github.com/elastio/bon/blob/master/benchmarks/runtime/README.md Installs necessary tools like cargo-show-asm and gungraun, and the Valgrind system package. Ensure you have Rust and Cargo installed first. ```bash cargo install cargo-show-asm gungraun-runner@$(cargo pkgid gungraun | cut -d@ -f2) sudo apt install valgrind ``` -------------------------------- ### Install hyperfine CLI Source: https://github.com/elastio/bon/blob/master/benchmarks/compilation/README.md Installs the hyperfine CLI tool, a dependency for running the benchmarks. This script is intended for Linux systems. ```bash ./scripts/install/hyperfine.sh ``` -------------------------------- ### Builder with Custom Method Example Source: https://github.com/elastio/bon/blob/master/website/src/guide/typestate-api/custom-methods.md Demonstrates a builder pattern with a custom method `example` that accepts a closure to configure the builder. It uses the `IsComplete` trait to manage required member bounds. ```rust use bon::Builder; #[derive(Builder)] struct ExampleParams { x1: u32, x2: u32, x3: Option, } // Our goal is to have this API example(|builder| builder.x1(1).x2(2)); // Below is how we could achieve this // Import traits from the generated module use example_params_builder::{State, IsSet}; fn example(f: impl FnOnce(ExampleParamsBuilder) -> ExampleParamsBuilder) where S: State, S::X1: IsSet, // [!code highlight] S::X2: IsSet, // [!code highlight] { let builder = f(ExampleParams::builder()); let params = builder.build(); } ``` -------------------------------- ### Run Local Development Server Source: https://github.com/elastio/bon/blob/master/website/README.md Execute this command within the `website` directory to start the local development server with hot reloading. ```bash npm run dev ``` -------------------------------- ### Configuring `start_fn` Name Source: https://github.com/elastio/bon/blob/master/website/src/reference/builder/top-level/start_fn.md This attribute configures just the name of the starting function. ```rust #[builder(start_fn = custom_name)] ``` -------------------------------- ### Configuring `start_fn` Name, Visibility, and Docs Source: https://github.com/elastio/bon/blob/master/website/src/reference/builder/top-level/start_fn.md This attribute provides more flexibility by allowing configuration of name, visibility, and documentation for the starting function. All keys are optional. ```rust #[builder( start_fn( name = custom_name, vis = "pub(crate)", doc { /// Custom docs } ) )] ``` -------------------------------- ### Function Builder Example with Top-Level and Member Attributes Source: https://github.com/elastio/bon/blob/master/website/src/reference/builder.md Shows how to apply `#[builder(finish_fn = finish)]` to a function and `#[builder(default)]` to its argument. ```rust use bon::builder; #[builder(finish_fn = finish)] // <-- this is a top-level attribute // [!code highlight] fn example( #[builder(default)] // <-- this is a member attribute // [!code highlight] arg: u32 ) { } ``` -------------------------------- ### Method with Positional Starting Function Members Source: https://github.com/elastio/bon/blob/master/website/src/guide/basics/positional-members.md For methods annotated with `#[bon::bon]`, `#[builder(start_fn)]` on parameters makes them available as positional arguments in the generated starting function. ```rust struct Example; #[bon::bon] impl Example { #[builder] fn display_treasure( #[builder(start_fn)] x: u32, #[builder(start_fn)] y: u32, label: Option, ) -> String { format!("{x}, {y}, {label:?}") } } let treasure = Example::display_treasure(2, 9) .label("oats".to_owned()) .call(); assert_eq!(treasure, r#"2, 9, Some("oats")"#) ``` -------------------------------- ### Basic Generics: Struct Example Source: https://github.com/elastio/bon/blob/master/website/src/reference/builder/top-level/generics.md Demonstrates using the `generics(setters = "with_{}")` attribute on a struct to generate methods for changing generic type parameters. Start with unit types and convert them to concrete types. ```rust use bon::Builder; #[derive(Builder)] #[builder(generics(setters = "with_{}"))] // [!code highlight] struct Example { data: TData, count: u32, } // Start with unit types, then convert to concrete types let example = Example::<()>::builder() .count(42) // Change TData from () to i32. Only possible if none // [!code highlight] // of the members that use `TData` generic are set // [!code highlight] .with_t_data::() .data(100) .build(); assert_eq!(example.data, 100_i32); assert_eq!(example.count, 42_u32); ``` -------------------------------- ### Define Positional Start Function Arguments Source: https://github.com/elastio/bon/blob/master/website/src/blog/bon-builder-v2-3-release.md Use `#[builder(start_fn = ...)]` and `#[builder(start_fn)]` to create a custom-named starting function with positional arguments for specified struct members. ```rust use bon::Builder; #[derive(Builder)] // Top-level attribute to give a better name for the starting function // [!code highlight] #[builder(start_fn = with_coordinates)] // [!code highlight] struct Treasure { // Member-level attribute to mark the member as // [!code highlight] // a parameter of `with_coordinates()` // [!code highlight] #[builder(start_fn)] // [!code highlight] x: u32, #[builder(start_fn)] // [!code highlight] y: u32, label: Option, } let treasure = Treasure::with_coordinates(2, 9) // [!code highlight] .label("oats".to_owned()) .build(); assert_eq!(treasure.x, 2); assert_eq!(treasure.y, 9); assert_eq!(treasure.label.as_deref(), Some("oats")); ``` -------------------------------- ### Long Syntax for `start_fn` with Visibility Source: https://github.com/elastio/bon/blob/master/website/src/reference/builder/top-level/start_fn.md The long syntax provides more flexibility, allowing configuration of name, visibility, and documentation. This example sets the name to `init` and visibility to `pub(crate)`. ```rust use bon::Builder; // `User::init()` method will have `pub(crate)` visibility // [!code highlight] // Use `vis = ""` to make it fully private instead // [!code highlight] #[derive(Builder)] #[builder(start_fn(name = init, vis = "pub(crate)"))] // [!code highlight] pub struct User { id: u32 } User::init() // [!code highlight] .id(42) .build(); ``` -------------------------------- ### Install Bon Crate Source: https://context7.com/elastio/bon/llms.txt Add the `bon` crate to your `Cargo.toml` file. Optional features like `implied_bounds` or `no_std` compatibility can be enabled. ```toml [dependencies] bon = "3.9" # Optional: enable associated-type implied bounds (raises MSRV to 1.79.0) # bon = { version = "3.9", features = ["implied_bounds"] } # For no_std environments: # bon = { version = "3.9", default-features = false } ``` -------------------------------- ### Method Builder Example with Top-Level and Member Attributes Source: https://github.com/elastio/bon/blob/master/website/src/reference/builder.md Illustrates using `#[builder(finish_fn = finish)]` on a method within an `impl` block and `#[builder(default)]` on its argument. ```rust use bon::bon; struct Example; #[bon] impl Example { #[builder(finish_fn = finish)] // <-- this is a top-level attribute // [!code highlight] fn example( #[builder(default)] // <-- this is a member attribute // [!code highlight] arg: u32 ) { } } ``` -------------------------------- ### Install and Run Bon CLI Migration Tool Source: https://github.com/elastio/bon/blob/master/website/src/blog/bon-builder-v2-2-release.md Use the `bon migrate` command to automatically update `#[builder]` usages on structs to `#[derive(Builder)]`. Ensure your working directory is clean before running. ```bash cargo install bon-cli bon migrate # Prettify the resulting code cargo fmt ``` -------------------------------- ### Python Named Function Arguments Example Source: https://github.com/elastio/bon/blob/master/website/src/blog/how-to-do-named-function-arguments-in-rust.md Demonstrates the syntax for named function arguments in Python, where arguments are passed using `key = value`. ```python def greet(name: str, age: int) -> str: return f"Hello {name} with age {age}!" greeting = greet( # Notice the `key = value` syntax at the call site # [!code highlight] name="Bon", # [!code highlight] age=24, # [!code highlight] ) assert greeting == "Hello Bon with age 24!" ``` -------------------------------- ### Struct with Positional Starting Function Members Source: https://github.com/elastio/bon/blob/master/website/src/guide/basics/positional-members.md Use `#[builder(start_fn)]` on struct members to include them as parameters in the generated starting function. This allows values to be passed positionally when creating the builder. ```rust #[derive(bon::Builder)] #[builder(start_fn = with_coordinates)] struct Treasure { #[builder(start_fn)] x: u32, #[builder(start_fn)] y: u32, label: Option, } let treasure = Treasure::with_coordinates(2, 9) .label("oats".to_owned()) .build(); assert_eq!(treasure.x, 2); assert_eq!(treasure.y, 9); assert_eq!(treasure.label.as_deref(), Some("oats")); ``` -------------------------------- ### Basic Generics: Function Example Source: https://github.com/elastio/bon/blob/master/website/src/reference/builder/top-level/generics.md Illustrates using the `generics(setters = "with_{}")` attribute on a function to generate methods for changing generic type parameters. This allows starting with unit types and converting them to concrete types. ```rust use bon::builder; #[builder(generics(setters = "with_{}"))] // [!code highlight] fn example( data: TData, count: u32 ) -> (TData, u32) { (data, count) } // Start with unit types, then convert to concrete types let example = example::<()>() .count(42) // Change TData from () to i32. Only possible if none // [!code highlight] // of the members that use `TData` generic are set // [!code highlight] .with_t_data::() .data(100) .call(); assert_eq!(example.0, 100_i32); assert_eq!(example.1, 42_u32); ``` -------------------------------- ### Documenting Function Arguments with #[bon::builder] Source: https://github.com/elastio/bon/blob/master/website/src/guide/basics/documenting.md Place documentation comments on function arguments to have them automatically applied to the generated setter methods. This is useful for providing detailed explanations and examples for each parameter. ```rust /// Function that returns a greeting special-tailored for a given person #[bon::builder] fn greet( /// Name of the person to greet. /// /// **Example:** /// ``` /// greet().name("John"); /// ``` name: &str, /// Age expressed in full years passed since the birth date. age: u32 ) -> String { format!("Hello {name} with age {age}!") } ``` -------------------------------- ### Generics with Custom Setters and Start Function Source: https://github.com/elastio/bon/blob/master/website/src/reference/builder/top-level/generics.md Demonstrates a more advanced use case of generics where custom setters and a custom start function are defined. This pattern addresses the 'optional generic members turbofish problem' by allowing generic types to default to `()` and be overwritten later. ```rust use bon::Builder; #[derive(Builder)] #[builder( generics(setters = "with_{}"), // [!code highlight] // Privatize the starting function, we'll define our own start_fn(vis = "", name = builder_internal), )] struct Data { // Privatize the setters, we'll define our own #[builder(setters(name = value_internal, vis = ""))] value: Option, } // Custom `builder()` method that begins with `T = ()` impl Data<()> { pub fn builder() -> DataBuilder<()> { Data::builder_internal() } } use data_builder::{State, SetValue, IsUnset}; // Custom setter, that overwrites `T` with the type of the provided value. impl DataBuilder { fn value(self, value: NewT) -> DataBuilder> where S::Value: IsUnset, { self.with_t().value_internal(value) // [!code highlight] } } // By default, the generic parameter is `()`. No type hints are required. let data_unit = Data::builder().build(); assert_eq!(data_unit.value, None); let data_u32 = Data::builder() .value(42) .build(); assert_eq!(data_u32.value, Some(42)); ``` -------------------------------- ### Duplicate Builder Configuration Source: https://github.com/elastio/bon/blob/master/website/src/guide/patterns/shared-configuration.md This example shows the problem of repeating the same builder configuration for multiple structs, leading to code duplication. ```rust use bon::Builder; #[derive(Builder)] #[builder( on(String, into), // [!code highlight] on(Box<_>, into), // [!code highlight] finish_fn = finish, // [!code highlight] )] struct MyLovelyStruct1 { /**/ } #[derive(Builder)] #[builder( on(String, into), // [!code highlight] on(Box<_>, into), // [!code highlight] finish_fn = finish, // [!code highlight] )] struct MyLovelyStruct2 { /**/ } ``` -------------------------------- ### Code Structure Comparison: `Good` vs `Bad` Source: https://github.com/elastio/bon/blob/master/website/src/guide/patterns/optional-generic-members.md Highlights the difference in type definitions between the `Good` example (concrete `Option`) and the `Bad` example (generic `Option` requiring manual conversion). ```rust #[bon::builder] fn good(#[builder(into)] x1: Option) { // ... } ``` ```rust #[bon::builder] fn bad>(x1: Option) { let x1 = x1.map(Into::into); // ... } ``` -------------------------------- ### buildstructor: Generating Collection Setters Source: https://github.com/elastio/bon/blob/master/website/src/guide/alternatives.md Example of how buildstructor automatically generates methods to build collections element by element. ```rust #[derive(buildstructor::Builder)] struct User { friends: Vec } fn main() { User::builder() .friend("Foo") .friend("Bar") .friend("`String` value is also accepted".to_owned()) .build(); } ``` -------------------------------- ### Struct Builder Example with Top-Level and Member Attributes Source: https://github.com/elastio/bon/blob/master/website/src/reference/builder.md Demonstrates using the `#[builder(finish_fn = finish)]` top-level attribute and the `#[builder(default)]` member attribute on a struct. ```rust use bon::Builder; #[derive(Builder)] #[builder(finish_fn = finish)] // <-- this is a top-level attribute // [!code highlight] struct Example { #[builder(default)] // <-- this is a member attribute // [!code highlight] field: u32 } ``` -------------------------------- ### Struct with derive(Builder) Source: https://github.com/elastio/bon/blob/master/website/src/guide/alternatives.md Example of a struct using the derive(Builder) macro for generating a builder API. ```rust use bon::Builder; #[derive(Builder)] pub struct Line { x1: u32, y1: u32, x2: u32, y2: u32, } // Suppose this is your users' code Line::builder().x1(1).y1(2).x2(3).y2(4).build(); ``` -------------------------------- ### Rust: Example without Into Conversions Source: https://github.com/elastio/bon/blob/master/website/src/guide/patterns/into-conversions-in-depth.md Demonstrates a scenario where `Into` conversions are not enabled, allowing `None` literals to be inferred correctly. This code compiles successfully. ```rust use bon::Builder; #[derive(Builder)] struct Example { member: Option } Example::builder() // Suppose we want to be explicit about omitting the `member`, // so we intentionally invoke the `maybe_` setter and pass `None` to it .maybe_member(None) .build(); ``` -------------------------------- ### Basic Generics: Method Example Source: https://github.com/elastio/bon/blob/master/website/src/reference/builder/top-level/generics.md Shows how to apply the `generics(setters = "with_{}")` attribute to a method to generate setters for generic type parameters. This enables transitioning from placeholder types to concrete types during the build process. ```rust use bon::bon; struct Example; #[bon] impl Example { #[builder(generics(setters = "with_{}"))] // [!code highlight] fn example( data: TData, count: u32 ) -> (TData, u32) { (data, count) } } // Start with unit types, then convert to concrete types let example = Example::example::<()>() .count(42) // Change TData from () to i32. Only possible if none // [!code highlight] // of the members that use `TData` generic are set // [!code highlight] .with_t_data::() .data(100) .call(); assert_eq!(example.0, 100_i32); assert_eq!(example.1, 42_u32); ``` -------------------------------- ### Method Argument `into` Example Source: https://github.com/elastio/bon/blob/master/website/src/reference/builder/member/into.md Shows the application of the `into` attribute to method arguments. This allows `&str` to be passed to `String` parameters and `Option<&str>` to optional `String` parameters. Default values are also subject to `Into::into` conversion. ```rust use bon::bon; struct Example; #[bon] impl Example { #[builder] fn example( #[builder(into)] // [!code highlight] name: String, #[builder(into)] // [!code highlight] description: Option, // The value passed to `default = ...` is converted with `into` as well // [!code highlight] #[builder(into, default = "anon")] // [!code highlight] group: String ) {} } Example::example() // We can pass `&str` because the setters accept `impl Into` // [!code highlight] .name("Bon") // [!code highlight] .description("Awesome crate 🐱. Consider giving it a star on Github ⭐") // [!code highlight] // We can pass `Option<&str>` to `maybe_` methods because they accept // [!code highlight] // `Option>` // [!code highlight] .maybe_group(Some("Favourites")) // [!code highlight] .call(); ``` -------------------------------- ### Basic Rust Doc Test Example Source: https://github.com/elastio/bon/blob/master/website/src/blog/the-weird-of-function-local-types-in-rust.md A simple Rust code snippet that can be used as a doc test. It is implicitly wrapped in a main function by rustdoc. ```rust let foo = 1 + 1; assert_eq!(foo, 2); ``` -------------------------------- ### Positional Members with `start_fn` and `finish_fn` Source: https://context7.com/elastio/bon/llms.txt Use `#[builder(start_fn)]` and `#[builder(finish_fn)]` to move struct members to the positional parameters of the starting or finishing function. ```rust use bon::Builder; // Members marked `start_fn` become positional args to the starting function. #[derive(Builder)] #[builder(start_fn = with_coords)] struct MapPin { #[builder(start_fn)] x: f64, #[builder(start_fn)] y: f64, label: Option, } let pin = MapPin::with_coords(48.8566, 2.3522) .label("Paris".to_owned()) .build(); assert_eq!(pin.x, 48.8566); ``` ```rust // Members marked `finish_fn` become positional args to the finishing function. #[derive(Builder)] #[builder(finish_fn = at)] struct Route { #[builder(finish_fn)] destination: String, mode: Option, } let route = Route::builder() .mode("walking".to_owned()) .at("Berlin".to_owned()); assert_eq!(route.destination, "Berlin"); ``` -------------------------------- ### Utility Collection Macros: `bon::vec!`, `bon::arr!`, `bon::map!`, `bon::set!` Source: https://context7.com/elastio/bon/llms.txt Utilize `bon`'s collection macros (`vec!`, `arr!`, `map!`, `set!`) to automatically apply `Into` conversions to elements, simplifying the creation of heterogeneous collections. Examples show building a `Vec`, a fixed-size array `[String; 2]`, a `HashMap`, and a `HashSet`. ```rust use std::collections::{HashMap, HashSet}; // bon::vec! — Vec with per-element Into conversion let args: Vec = bon::vec![ "-i", format!("input.mp4"), "-y", "output.mkv", ]; assert_eq!(args[0], "-i"); // bon::arr! — fixed-size array with Into conversion let flags: [String; 2] = bon::arr!["--verbose", "--debug"]; // bon::map! — HashMap / BTreeMap with Into conversion on keys and values let headers: HashMap = bon::map! { "Content-Type": "application/json", "Authorization": "Bearer token123", }; assert_eq!(headers["Content-Type"], "application/json"); // bon::set! — HashSet / BTreeSet with Into conversion let allowed: HashSet = bon::set!["GET", "POST", "PUT"]; assert!(allowed.contains("GET")); ``` -------------------------------- ### Function with Positional Starting Function Members Source: https://github.com/elastio/bon/blob/master/website/src/guide/basics/positional-members.md When using `#[bon::builder]` on a function, `#[builder(start_fn)]` on its parameters moves them to the function's signature, enabling positional argument passing. ```rust #[bon::builder] fn display_treasure( #[builder(start_fn)] x: u32, #[builder(start_fn)] y: u32, label: Option, ) -> String { format!("{x}, {y}, {label:?}") } let treasure = display_treasure(2, 9) .label("oats".to_owned()) .call(); assert_eq!(treasure, r#"2, 9, Some( ``` -------------------------------- ### Reusable Function Builder Configuration with macro_rules_attribute Source: https://github.com/elastio/bon/blob/master/website/src/guide/patterns/shared-configuration.md This example shows how to create a shared configuration for function builders using `attribute_alias` from `macro_rules_attribute`, enabling reuse across multiple functions. ```rust use macro_rules_attribute::{attribute_alias, apply}; attribute_alias! { #[apply(builder!)] = #[::bon::builder( on(String, into), // [!code highlight] on(Box<_>, into), // [!code highlight] finish_fn = finish, // [!code highlight] )]; } #[apply(builder!)] fn my_lovely_fn1(/**/) { /**/ } #[apply(builder!)] fn my_lovely_fn2(/**/) { /**/ } ``` -------------------------------- ### Exposing Original Method with `start_fn` Source: https://github.com/elastio/bon/blob/master/website/src/reference/builder/top-level/start_fn.md Demonstrates using `start_fn` with methods to keep the original method and its builder syntax available. The `name` parameter is required for `fn` syntax. ```rust use bon::bon; struct Example; #[bon] impl Example { #[builder(start_fn = builder)] fn new(x: u32, y: u32) -> Self { Example } #[builder(start_fn = method_builder)] fn method(&self, x: u32, y: u32) {} } // The original method `new` is still available Example::new(1, 2); // The builder syntax is also available under the given name let example = Example::builder() .x(1) .y(2) .build(); // The original `method` is still available example.method(1, 2); // The builder syntax for the `method` is also available under the given name example.method_builder() .x(1) .y(2) .call(); ``` -------------------------------- ### Method Argument as Positional Argument Source: https://github.com/elastio/bon/blob/master/website/src/reference/builder/member/start_fn.md Apply `#[builder(start_fn)]` to method parameters to make them positional arguments in the builder's starting function. This example illustrates a method where `x1` and `x2` are provided positionally. ```rust use bon::bon; struct Example; #[bon] impl Example { #[builder] fn example( #[builder(start_fn)] // [!code highlight] x1: u32, #[builder(start_fn)] // [!code highlight] x2: u32, x3: u32, ) -> (u32, u32, u32) { (x1, x2, x3) } } let value = Example::example(1, 2) // [!code highlight] .x3(3) .call(); assert_eq!(value.0, 1); assert_eq!(value.1, 2); assert_eq!(value.2, 3); ``` -------------------------------- ### Function Argument as Positional Argument Source: https://github.com/elastio/bon/blob/master/website/src/reference/builder/member/start_fn.md Annotate function parameters with `#[builder(start_fn)]` to make them positional arguments in the builder's starting function. This example shows a function where `x1` and `x2` are passed positionally. ```rust use bon::builder; #[builder] fn example( #[builder(start_fn)] // [!code highlight] x1: u32, #[builder(start_fn)] // [!code highlight] x2: u32, x3: u32, ) -> (u32, u32, u32) { (x1, x2, x3) } let value = example(1, 2) // [!code highlight] .x3(3) .call(); assert_eq!(value.0, 1); assert_eq!(value.1, 2); assert_eq!(value.2, 3); ``` -------------------------------- ### Struct Field as Positional Argument Source: https://github.com/elastio/bon/blob/master/website/src/reference/builder/member/start_fn.md Use `#[builder(start_fn)]` on struct fields to make them positional arguments in the generated builder's starting function. The example demonstrates initializing a struct where `x1` and `x2` are set positionally. ```rust use bon::Builder; #[derive(Builder)] struct Example { #[builder(start_fn)] // [!code highlight] x1: u32, #[builder(start_fn)] // [!code highlight] x2: u32, x3: u32, } let value = Example::builder(1, 2) // [!code highlight] .x3(3) .build(); assert_eq!(value.x1, 1); assert_eq!(value.x2, 2); assert_eq!(value.x3, 3); ``` -------------------------------- ### Manual Into Conversions for Methods Source: https://github.com/elastio/bon/blob/master/website/src/guide/basics/into-conversions.md Illustrates manual conversion in a method implementation using `.to_owned()`, `.to_string()`, and `.into()`. ```rust use std::path::PathBuf; struct Example; #[bon::bon] // [!code focus] impl Example { #[builder] // [!code focus] fn example( // [!code focus] name: String, // [!code focus] description: String, // [!code focus] path: PathBuf, // [!code focus] ) {} // [!code focus] } Example::example() .name("Bon".to_owned()) // [!code focus] .description("Awesome crate 🐱".to_string()) // [!code focus] .path("/path/to/bon".into()) // [!code focus] .call(); ``` -------------------------------- ### Bon Builder Macro Usage Source: https://github.com/elastio/bon/blob/master/website/src/blog/bon-builder-v2-1-release.md Demonstrates the usage of the `#[bon::builder]` macro for generating a builder for a struct. Shows how to instantiate and partially build a struct, and highlights common errors like forgetting members or setting members twice. ```rust #[bon::builder] struct Point3D { x: f64, y: f64, z: f64, } fn main() { // Not all members are set let _ = Point3D::builder() .x(1.0) .build(); let _ = Point3D::builder() .x(2.0) .y(3.0) .x(4.0) // <--- Oops, `x` was set the second time instead of `z` .build(); } ``` -------------------------------- ### Configure `finish_fn` Name, Visibility, and Docs Source: https://github.com/elastio/bon/blob/master/website/src/reference/builder/top-level/finish_fn.md Use the long syntax to provide custom name, visibility, and documentation for the finishing function. All keys are optional. ```rust #[builder( finish_fn( name = custom_name, vis = "pub(crate)", doc { /// Custom docs } ) )] ``` -------------------------------- ### Exposing Original Function with `start_fn` Source: https://github.com/elastio/bon/blob/master/website/src/reference/builder/top-level/start_fn.md Use `start_fn` to keep the original function accessible when using builder syntax. The `name` parameter is required for `fn` syntax. ```rust use bon::builder; #[builder(start_fn = example_builder)] // [!code ++] fn example(x: u32, y: u32) {} // The original positional function is still available example(1, 2); // The builder syntax is also available under the given name example_builder() .x(1) .y(2) .call(); ``` -------------------------------- ### Bon Builder Macro Usage Source: https://github.com/elastio/bon/blob/master/website/src/blog/bon-v3-release.md Demonstrates how to use the Bon builder macro for functions, including setting optional parameters and calling the generated function. Imports for generated type states are shown. ```rust #[bon::builder] fn greet(level: Option<&str>, name: &str) -> String { format!("[{}] {name} says hello!", level.unwrap_or("DEBUG")) } // Import type states from the generated module (private by default) use greet_builder::{SetName, SetLevel}; // Builder type states have stable readable names 🎉 let builder: GreetBuilder = greet().name("Bon"); let builder: GreetBuilder> = builder.level("INFO"); // ^^^^^ optional to set assert_eq!("[INFO] Bon says hello!", builder.call()); ``` -------------------------------- ### Manual Into Conversions for Structs Source: https://github.com/elastio/bon/blob/master/website/src/guide/basics/into-conversions.md Demonstrates manual conversion using `.to_owned()`, `.to_string()`, and `.into()` for struct members. ```rust use std::path::PathBuf; #[derive(bon::Builder)] // [!code focus] struct Example { // [!code focus] name: String, // [!code focus] description: String, // [!code focus] path: PathBuf, // [!code focus] } // [!code focus] Example::builder() .name("Bon".to_owned()) // [!code focus] .description("Awesome crate 🐱".to_string()) // [!code focus] .path("/path/to/bon".into()) // [!code focus] .build(); ``` -------------------------------- ### Get Type Name of Local Struct Source: https://github.com/elastio/bon/blob/master/website/src/blog/the-weird-of-function-local-types-in-rust.md Demonstrates how `std::any::type_name()` includes the function name in the path for local types. ```rust fn example() -> &'static str { struct User; std::any::type_name::() } fn main() { println!("{}", example()); } ``` -------------------------------- ### Field Initialization with Expressions Source: https://github.com/elastio/bon/blob/master/website/src/reference/builder/member/field.md Demonstrates initializing builder fields using expressions that reference previously declared fields. `x2` is initialized based on `x1`, and `x3` is initialized based on both `x1` and `x2`. ```rust use bon::Builder; #[derive(Builder)] struct Example { #[builder(start_fn)] x1: u32, // Note that here we don't have access to `x3` // because it's declared (and thus initialized) later #[builder(field = 2 * x1)] x2: u32, #[builder(field = x2 + x1)] x3: u32, } let example = Example::builder(3).build(); assert_eq!(example.x1, 3); assert_eq!(example.x2, 6); assert_eq!(example.x3, 9); ``` -------------------------------- ### Cargo.toml Configuration for Implied Bounds Source: https://github.com/elastio/bon/blob/master/website/src/guide/typestate-api/custom-methods.md Example of how to enable the `implied-bounds` feature for the `bon` crate in your `Cargo.toml` file. This requires Rust 1.79.0 or later. ```toml [dependencies] bon = { version = "3.9", features = ["implied-bounds"] } ``` -------------------------------- ### Example of Setter Name Overriding Source: https://github.com/elastio/bon/blob/master/website/src/reference/builder/member/setters.md Illustrates how to use the `setters` attribute to override the default names of generated setters for both required and optional members. ```rust #[derive(bon::Builder)] struct Example { #[builder(setters(name = foo, some_fn = bar))] member: Option, } // Name of `some_fn` that accepts the non-None value was overridden Example::builder().bar(2).build(); // Name of `option_fn` was derived from the root-level `setters(name)` Example::builder().maybe_foo(Some(2)).build(); ``` -------------------------------- ### Configure Builder Struct Name, Visibility, and Docs Source: https://github.com/elastio/bon/blob/master/website/src/reference/builder/top-level/builder_type.md Use the long syntax for detailed configuration of the builder struct, including name, visibility, and documentation comments. All keys are optional. ```rust #[builder( builder_type( name = CustomName, vis = "pub(crate)", doc { /// Custom docs } ) )] ``` -------------------------------- ### Setter Documentation Configuration (`doc`) Source: https://github.com/elastio/bon/blob/master/website/src/reference/builder/member/setters.md Explains how to override or skip documentation generation for setters. ```APIDOC ## Setter Documentation (`doc`) ### Description Provides options to customize or suppress documentation generation for builder setters. ### Configuration Options - **`doc {...}`**: Overrides the auto-generated documentation content for a setter with custom doc comments provided within the curly braces. This does not affect the auto-generated documentation header. ```attr doc { /// Custom documentation for this setter. } ``` - **`doc(default(skip))`**: Specifically for optional setters that utilize the `#[builder(default)]` attribute, this option prevents the default value from being included in the auto-generated documentation header. ### Example ```rust #[derive(bon::Builder)] struct Configurable { #[builder(setters(doc { /// Sets the custom value }, doc(default(skip))))] value: Option, } // The setter for `value` will have custom docs, and its default value will be omitted from generated docs. ``` ``` -------------------------------- ### bon: Using `bon::vec!` Macro for Collections Source: https://github.com/elastio/bon/blob/master/website/src/guide/alternatives.md Demonstrates using the `bon::vec!` macro to initialize a `Vec` with items of type `&str`, leveraging `Into` conversion. ```rust use bon::Builder; #[derive(Builder)] struct User { friends: Vec } User::builder() .friends(bon::vec![ "Foo", "Bar", "`String` value is also accepted".to_owned(), ]) .build(); ``` -------------------------------- ### Custom Getter Documentation Source: https://github.com/elastio/bon/blob/master/website/src/reference/builder/member/getter.md Illustrates how to provide custom documentation comments for a generated getter method using the `doc` configuration within the `getter` attribute. ```rust doc { /// Doc comments } ``` -------------------------------- ### Run Benchmarks Source: https://github.com/elastio/bon/blob/master/benchmarks/compilation/README.md Executes a selected benchmark using the run.sh script. Replace {benchmark_name} with the specific module name to benchmark. ```bash ./run.sh {benchmark_name} ``` -------------------------------- ### Avoid `Into` for Performance-Sensitive Code Source: https://github.com/elastio/bon/blob/master/website/src/guide/patterns/into-conversions-in-depth.md When performance is critical, avoid `impl Into` to prevent unintentional heap allocations or data cloning. This example shows how passing a reference can lead to cloning. ```rust use bon::builder; #[builder] fn process_heavy_json(#[builder(into)] data: String) { /* */ } let json = String::from( r#"{ \"key\": \"Pretend this is a huge JSON string with hundreds of MB in size\" }"# ); process_heavy_json() // Whoops, we passed a `&String`. // [!code error] // The builder will clone the data internally. // [!code error] .data(&json) // [!code error] .call(); ``` -------------------------------- ### Defining and Using Custom Builder Fields Source: https://github.com/elastio/bon/blob/master/website/src/guide/typestate-api/builder-fields.md Illustrates defining a custom field `args` using `#[builder(field)]` and implementing custom methods `arg` and `args` on the builder to manipulate this field. ```rust use bon::Builder; #[derive(Builder)] struct Command { // Define a private field on the builder without setters. // [!code highlight] // It's initialized with `Default::default()` at the start // [!code highlight] #[builder(field)] // [!code highlight] args: Vec, #[builder(into)] name: String, } // This is the API we'd like to have // [!code highlight] let cmd = Command::builder() .name("ls") .arg("-l") .args(["foo", "bar"]) .build(); assert_eq!(cmd.name, "ls"); assert_eq!(cmd.args, ["-l", "foo", "bar"]); // Now define custom `arg/args` methods on the builder itself. // [!code highlight] impl CommandBuilder { fn arg(mut self, arg: impl Into) -> Self { // We have access to `self.args` private 🔒 field on `CommandBuilder`! // [!code highlight] self.args.push(arg.into()); // [!code highlight] self } fn args(mut self, args: impl IntoIterator>) -> Self { self.args.extend(args.into_iter().map(Into::into)); self } } ``` -------------------------------- ### Struct with Positional Members Source: https://github.com/elastio/bon/blob/master/website/src/guide/basics/positional-members.md Use `#[builder(finish_fn)]` on struct members to move them to the parameters of the custom finishing function. This example shows how `x` and `y` are moved to the `located_at` function parameters. ```rust #[derive(bon::Builder)] // Top-level attribute to give a custom name for the finishing function // [!code highlight] #[builder(finish_fn = located_at)] // [!code highlight] struct Treasure { // Member-level attributes to move members // [!code highlight] // to the parameters of `located_at()` // [!code highlight] #[builder(finish_fn)] // [!code highlight] x: u32, #[builder(finish_fn)] // [!code highlight] y: u32, label: Option, } let treasure = Treasure::builder() .label("oats".to_owned()) .located_at(2, 9); // [!code highlight] assert_eq!(treasure.x, 2); assert_eq!(treasure.y, 9); assert_eq!(treasure.label.as_deref(), Some("oats")); ``` -------------------------------- ### Using #[bon::builder] on Structs Source: https://github.com/elastio/bon/blob/master/website/src/blog/bon-builder-v2-2-release.md Demonstrates the original syntax for applying the `#[bon::builder]` macro to structs. This attribute should be placed on a separate line. ```rust #[bon::builder] #[derive(Debug, Clone, serde::Serialize)] struct Example { // ... } ``` -------------------------------- ### Generated Code Comparison: `builder(into)` vs `Option` Source: https://github.com/elastio/bon/blob/master/website/src/guide/patterns/optional-generic-members.md Compares the generated builder code for `#[builder(into)]` and `Option` to illustrate how generics are handled differently. ```rust fn good() -> GoodBuilder { /**/ } impl GoodBuilder { fn x1(self, value: impl Into) -> GoodBuilder> { GoodBuilder { /* other fields */, __x1: value.into() } } } ``` ```rust fn bad() -> BadBuilder { /**/ } impl, S: State> BadBuilder { fn x1(self, value: T) -> BadBuilder> { BadBuilder { /* other fields */, __x1: value } } } ``` -------------------------------- ### Fallible Closure for Function Builder Source: https://github.com/elastio/bon/blob/master/website/src/reference/builder/member/with.md This example demonstrates using a fallible closure with a `Result` return type for a function builder. The closure transforms the input string into a `u32`, making the setter fallible. ```rust use bon::builder; use std::num::ParseIntError; #[builder] fn example( #[builder(with = |string: &str| -> Result<_, ParseIntError> { string.parse() })] x1: u32, ) -> u32 { x1 } fn main() -> Result<(), ParseIntError> { example() .x1("99")? // <-- the setter returns a `Result` .call(); Ok(()) } ``` -------------------------------- ### Function-based builder with bon Source: https://github.com/elastio/bon/blob/master/website/src/guide/alternatives.md Illustrates how to use bon's function-based builder to decouple the builder API from the struct's internal representation, allowing for refactoring without breaking changes. ```rust use bon::bon; pub struct Line { point1: Point, point2: Point, } struct Point { x: u32, y: u32, } #[bon] impl Line { #[builder] fn new(x1: u32, y1: u32, x2: u32, y2: u32) -> Self { Self { point1: Point { x: x1, y: y1 } , point2: Point { x: x2, y: y2 } , } } } // Suppose this is your users' code (it compiles after this change, yay 🎉!) Line::builder().x1(1).y1(2).x2(3).y2(4).build(); ``` -------------------------------- ### Function Argument with `name` Attribute Source: https://github.com/elastio/bon/blob/master/website/src/reference/builder/member/name.md Apply the `name` attribute to a function argument to control its name within the generated builder. This example demonstrates mapping a `level` parameter to a `rank` argument in the builder. ```rust use bon::builder; #[builder] fn player( #[builder(name = rank)] // [!code highlight] level: u32 ) {} player() .rank(10) // [!code highlight] .call(); ``` -------------------------------- ### Rust: Compile-fail Example with Into Conversions Source: https://github.com/elastio/bon/blob/master/website/src/guide/patterns/into-conversions-in-depth.md Illustrates a compilation failure when `Into` conversions are enabled for an `Option` field, causing type inference issues with `None` literals. The compiler cannot infer the generic type within `Option`. ```rust use bon::Builder; #[derive(Builder)] struct Example { #[builder(into)] // [!code ++] member: Option } Example::builder() .maybe_member(None) .build(); ``` -------------------------------- ### Struct Field with `name` Attribute Source: https://github.com/elastio/bon/blob/master/website/src/reference/builder/member/name.md Use the `name` attribute on a struct field to define the name used in the builder API. This example shows how to map an internal `level` field to a `rank` setter in the builder. ```rust use bon::Builder; #[derive(Builder)] struct Player { #[builder(name = rank)] // [!code highlight] level: u32 } Player::builder() .rank(10) // [!code highlight] .build(); ``` -------------------------------- ### Manual Into Conversions for Functions Source: https://github.com/elastio/bon/blob/master/website/src/guide/basics/into-conversions.md Shows manual conversion within a function context using `.to_owned()`, `.to_string()`, and `.into()`. ```rust use std::path::PathBuf; #[bon::builder] // [!code focus] fn example( // [!code focus] name: String, // [!code focus] description: String, // [!code focus] path: PathBuf, // [!code focus] ) {} // [!code focus] example() .name("Bon".to_owned()) // [!code focus] .description("Awesome crate 🐱".to_string()) // [!code focus] .path("/path/to/bon".into()) // [!code focus] .call(); ```