2 unstable releases
new 0.2.0 | Nov 3, 2024 |
---|---|
0.1.0 | Sep 8, 2024 |
#73 in Procedural macros
12KB
136 lines
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.
Quick examples
Builder for a free function
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");
Builder for an associated method
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");
Builder for a struct
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 more.
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 🐱!
License
Licensed under either of Apache License, Version 2.0 or MIT license at your option.Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
Dependencies
~4–11MB
~119K SLoC