Next-gen compile-time-checked builder generator, named function's arguments, and more!
APACHE-2.0 License
bon
is a Rust crate for generating compile-time-checked builders for functions and structs. It also provides idiomatic partial application with optional and named parameters for functions and methods.
Visit the guide for a complete overview of the crate.
You can turn a function with positional parameters into a function with named parameters just by placing the #[builder]
attribute on top of it.
use bon::builder;
#[builder]
fn greet(name: &str, level: Option<u32>) -> String {
let level = level.unwrap_or(0);
format!("Hello {name}! Your level is {level}")
}
let greeting = greet()
.name("Bon")
.level(24) // <- setting `level` is optional, we could omit it
.call();
assert_eq!(greeting, "Hello Bon! Your level is 24");
For associated methods you also need to add the #[bon]
macro on top of the impl block.
use bon::bon;
struct User {
id: u32,
name: String,
}
#[bon] // <- this attribute is required on impl blocks that contain `#[builder]`
impl User {
#[builder]
fn new(id: u32, name: String) -> Self {
Self { id, name }
}
#[builder]
fn greet(&self, target: &str, level: Option<&str>) -> String {
let level = level.unwrap_or("INFO");
let name = &self.name;
format!("[{level}] {name} says hello to {target}")
}
}
// The method named `new` generates `builder()/build()` methods
let user = User::builder()
.id(1)
.name("Bon".to_owned())
.build();
// All other methods generate `method_name()/call()` methods
let greeting = user
.greet()
.target("the world")
// `level` is optional, we can omit it here
.call();
assert_eq!(user.id, 1);
assert_eq!(user.name, "Bon");
assert_eq!(greeting, "[INFO] Bon says hello to the world");
The #[derive(Builder)]
macro generates a builder for a struct.
use bon::Builder;
#[derive(Builder)]
struct User {
name: String,
is_admin: bool,
level: Option<u32>,
}
let user = User::builder()
.name("Bon".to_owned())
// `level` is optional, we could omit it here
.level(24)
// call setters in any order
.is_admin(true)
.build();
assert_eq!(user.name, "Bon");
assert_eq!(user.level, Some(24));
assert!(user.is_admin);
See the guide for the rest.
If you like the idea of this crate and want to say "thank you" or "keep doing this" consider giving us a star ⭐ on Github. Any support and contribution are appreciated 🐱!