[go: up one dir, main page]

Crate bon

source ·
Expand description
bon home

github crates.io docs.rs docs.rs

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 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 🐱!

§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.

Macros§

Attribute Macros§

  • Companion macro for builder. You should place it on top of the impl block where you want to define methods with the builder macro.
  • Generates a builder for the function or method it’s placed on.

Derive Macros§

  • Derives a builder for the struct it’s placed on.