Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ jobs:
- uses: actions-rust-lang/setup-rust-toolchain@v1
with:
toolchain: nightly-2024-10-30
components: miri
components: miri, rust-src

- run: |
cargo miri test --locked --all-features --all-targets \
Expand Down
22 changes: 10 additions & 12 deletions README.v3.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ assert_eq!(greeting, "Hello Bon! Your level is 24");

Any syntax for functions is supported including `async`, fallible, generic functions, `impl Trait`, etc.

Many things are customizable with additional attributes described in the [API reference](https://bon-rs.com/reference/builder), but let's see what else `bon` offers.
Many things are customizable with additional attributes described in the [API reference](https://bon-rs.com/reference/builder), but let's see what else `bon` has to offer.

## Struct Builder

Expand Down Expand Up @@ -137,7 +137,7 @@ assert_eq!(user.id, 1);
assert_eq!(user.name, "Bon");
```

`#[derive(Builder)]` on a struct generates builder API that is fully compatible with placing `#[builder]` on the `new()` method with a signature similar to the struct's fields (more details on the [Compatibility](https://bon-rs.com/guide/misc/compatibility#switching-between-derive-builder-and-builder-on-the-new-method) page).
`#[derive(Builder)]` on a struct generates builder API that is fully compatible with placing `#[builder]` on the `new()` method with a signature similar to the struct's fields (more details on the [Compatibility](https://bon-rs.com/guide/basics/compatibility#switching-between-derive-builder-and-builder-on-the-new-method) page).

### Other Methods

Expand Down Expand Up @@ -176,16 +176,14 @@ Methods with or without `self` are both supported.

## No Panics Possible

Builders generated by `bon`'s macros use the typestate pattern to ensure all required parameters are filled, and the same setters aren't called repeatedly to prevent unintentional overwrites.

If something is wrong, a compile error will be created. No matter how you use the generated builder a panic is never possible.
Builders generated by `bon`'s macros use the typestate pattern to ensure all required parameters are filled, and the same setters aren't called repeatedly to prevent unintentional overwrites. If something is wrong, a compile error will be created.

| ⭐ Don't forget to give our repo a [star on Github ⭐](https://github.com/elastio/bon)! |
| --------------------------------------------------------------------------------------- |

## What's Next?

What you've seen above is the first page of the 📖 [Guide Book](https://bon-rs.com/guide/overview). Consider reading the `Basics` section. Begin [here](https://bon-rs.com/guide/basics/optional-members) with the optional/default values topic. Remember, knowledge is power 🐱!
What you've seen above is the first page of the 📖 Guide Book. If you want to learn more, jump to the [Basics](https://bon-rs.com/guide/basics) section. And remember: knowledge is power 🐱!

Feel free to jump to code and use the `#[builder]` and `#[derive(Builder)]` once you've seen enough docs to get started.

Expand All @@ -202,6 +200,12 @@ bon = "2.3"

You can opt out of `std` and `alloc` cargo features with `default-features = false` for `no_std` environments.

## Acknowledgments

This project was heavily inspired by such awesome crates as [`buildstructor`](https://docs.rs/buildstructor), [`typed-builder`](https://docs.rs/typed-builder) and [`derive_builder`](https://docs.rs/derive_builder). This crate was designed with many lessons learned from them.

See [alternatives](https://bon-rs.com/guide/alternatives) for comparison.

## Getting Help

If you can't figure something out, consult the docs and maybe use the `🔍 Search` bar on our [docs website](https://bon-rs.com). You may also create an issue or a discussion on the [Github repository](https://github.com/elastio/bon) for help or write us a message on [Discord](https://bon-rs.com/discord).
Expand All @@ -221,12 +225,6 @@ If you can't figure something out, consult the docs and maybe use the `🔍 Sear
</tbody>
</table>

## Acknowledgments

This project was heavily inspired by such awesome crates as [`buildstructor`](https://docs.rs/buildstructor), [`typed-builder`](https://docs.rs/typed-builder) and [`derive_builder`](https://docs.rs/derive_builder). This crate was designed with many lessons learned from them.

See [alternatives](https://bon-rs.com/guide/misc/alternatives) for comparison.

## License

<sup>
Expand Down
4 changes: 3 additions & 1 deletion benchmarks/runtime/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,12 @@ sudo apt install valgrind

## Running the benchmarks

Once you have all the [dependencies](#dependencies) installed you can run the selected benchmark from this directory like this:
Once you have all the [dependencies](#dependencies) installed you can run the selected benchmarks from this directory like this:

```bash
./run.sh {benchmark_name}
```

The `{benchmark_name}` corresponds to the modules in this crate. The number in the benchmark name represents the number of arguments that are passed to the function.

If you don't pass any parameter to `run.sh`, it will run all benchmarks.
25 changes: 13 additions & 12 deletions benchmarks/runtime/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,22 @@

set -euxo pipefail

bench=${1:-args_10_structs}
# Run all benchmarks by default
benches=${1:-$(find src -name '*.rs' | sed 's/\.rs$//' | sed 's/src\///' | grep -v lib)}

export CARGO_INCREMENTAL=0

cargo clean
for bench in $benches; do
cargo build --features "$bench" --release -p runtime-benchmarks

cargo build --features "$bench" --release -p runtime-benchmarks
# If vscode is present, show diff:
if command -v code; then
cargo asm --features "$bench" --no-color "runtime_benchmarks::$bench::builder_bench" > builder.dbg.s || true
cargo asm --features "$bench" --no-color "runtime_benchmarks::$bench::regular_bench" > regular.dbg.s || true

cargo asm --features "$bench" --no-color "runtime_benchmarks::$bench::builder_bench" > builder.dbg.s || true
cargo asm --features "$bench" --no-color "runtime_benchmarks::$bench::regular_bench" > regular.dbg.s || true
code --diff regular.dbg.s builder.dbg.s
fi

# If vscode is present, show diff:
if command -v code; then
code --diff regular.dbg.s builder.dbg.s
fi

cargo bench --features "$bench" -p runtime-benchmarks --profile release --bench iai
cargo bench --features "$bench" -p runtime-benchmarks --profile release --bench criterion
cargo bench --features "$bench" -p runtime-benchmarks --profile release --bench iai
cargo bench --features "$bench" -p runtime-benchmarks --profile release --bench criterion
done
2 changes: 1 addition & 1 deletion benchmarks/runtime/src/args_10.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ pub fn builder_bench() -> u32 {
.call()
}

#[builder(start_fn = builder)]
#[builder(crate = crate::bon, start_fn = builder)]
fn regular(
arg1: &str,
arg2: u32,
Expand Down
2 changes: 1 addition & 1 deletion benchmarks/runtime/src/args_10_alloc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ pub fn builder_bench() -> u32 {
.call()
}

#[builder(start_fn = builder)]
#[builder(crate = crate::bon, start_fn = builder)]
fn regular(
arg1: String,
arg2: u32,
Expand Down
2 changes: 1 addition & 1 deletion benchmarks/runtime/src/args_10_structs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ pub fn builder_bench() -> u32 {
.call()
}

#[builder(start_fn = builder)]
#[builder(crate = crate::bon, start_fn = builder)]
fn regular(
arg1: Point3D,
arg2: u32,
Expand Down
2 changes: 1 addition & 1 deletion benchmarks/runtime/src/args_20.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ pub fn builder_bench() -> u32 {
.call()
}

#[builder(start_fn = builder)]
#[builder(crate = crate::bon, start_fn = builder)]
fn regular(
arg1: &str,
arg2: u32,
Expand Down
2 changes: 1 addition & 1 deletion benchmarks/runtime/src/args_3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ pub fn builder_bench() -> u32 {
builder().arg1(arg1).arg2(arg2).maybe_arg3(arg3).call()
}

#[builder(start_fn = builder)]
#[builder(crate = crate::bon, start_fn = builder)]
fn regular(arg1: &str, arg2: u32, arg3: Option<&str>) -> u32 {
let x = arg1.parse::<u32>().unwrap() + arg2;
let x = x + arg3.map(|x| x.parse::<u32>().unwrap()).unwrap_or(0);
Expand Down
2 changes: 1 addition & 1 deletion benchmarks/runtime/src/args_5.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ pub fn builder_bench() -> u32 {
.call()
}

#[builder(start_fn = builder)]
#[builder(crate = crate::bon, start_fn = builder)]
fn regular(arg1: &str, arg2: u32, arg3: bool, arg4: Option<&str>, arg5: Option<u32>) -> u32 {
let x = arg1.parse::<u32>().unwrap() + arg2;
let x = x + u32::from(arg3);
Expand Down
6 changes: 6 additions & 0 deletions benchmarks/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@
rustdoc::missing_crate_level_docs
)]

// This reexport makes it easier to prepare the ASM comparison since the
// generated code refers to a local modules that can be manually replaced
// on godbolt to avoid referencing a 3rd party crate.
#[allow(clippy::single_component_path_imports)]
use bon;

cfg_if::cfg_if! {
if #[cfg(feature = "args_3")] {
pub mod args_3;
Expand Down
12 changes: 0 additions & 12 deletions bon/src/__/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,3 @@ pub struct Unset<Name>(Name);

#[derive(Debug)]
pub struct Set<Name>(Name);

#[rustversion::attr(
since(1.78.0),
diagnostic::on_unimplemented(
message = "expected type state for the member `{Name}`, but got `{Self}`",
label = "expected type state for the member `{Name}`, but got `{Self}`",
)
)]
pub trait MemberState<Name>: Sealed {}

impl<Name> MemberState<Name> for Unset<Name> {}
impl<Name> MemberState<Name> for Set<Name> {}
2 changes: 1 addition & 1 deletion e2e-tests/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ fn main() {
.join("\n");

format!(
"#[doc = r###\"{doc}\"###] \
"#[doc = r#####\"{doc}\"#####] \
mod {test_name} {{}}"
)
})
Expand Down
55 changes: 33 additions & 22 deletions website/.vitepress/config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ export default defineConfig({
"Function that creates the builder (e.g. `builder()`)",
["finishing function"]:
"Method on the builder struct that finishes building (e.g. `build()` or `call()`)",
["underlying type"]:
"For required members, it's the type of the member itself. " +
"For optional members, it's the type `T` inside of the `Option<T>`",
};

const abbrsStr = Object.entries(abbrs)
Expand Down Expand Up @@ -130,8 +133,13 @@ export default defineConfig({
text: "Overview",
link: "/guide/overview",
},
{
text: "Alternatives",
link: "/guide/alternatives",
},
{
text: "Basics",
link: "/guide/basics",
items: [
{
text: "Optional Members",
Expand All @@ -157,6 +165,10 @@ export default defineConfig({
text: "Documenting",
link: "/guide/basics/documenting",
},
{
text: "Compatibility",
link: "/guide/compatibility",
},
],
},
{
Expand All @@ -175,6 +187,7 @@ export default defineConfig({
},
{
text: "Patterns",
link: "/guide/patterns",
items: [
{
text: "Conditional Building",
Expand All @@ -184,6 +197,10 @@ export default defineConfig({
text: "Fallible Builders",
link: "/guide/patterns/fallible-builders",
},
{
text: "Optional Generic Members",
link: "/guide/patterns/optional-generic-members",
},
{
text: "Into Conversions In-Depth",
link: "/guide/patterns/into-conversions-in-depth",
Expand All @@ -195,39 +212,33 @@ export default defineConfig({
],
},
{
text: "Misc",
text: "Benchmarks",
link: "/guide/benchmarks",
items: [
{
text: "Compatibility",
link: "/guide/misc/compatibility",
},
{
text: "Limitations",
link: "/guide/misc/limitations",
text: "Runtime",
link: "/guide/benchmarks/runtime",
},
{
text: "Benchmarks",
link: "/guide/misc/benchmarks",
},
{
text: "Alternatives",
link: "/guide/misc/alternatives",
},
{
text: "Troubleshooting",
link: "/guide/misc/troubleshooting",
text: "Compilation",
link: "/guide/benchmarks/compilation",
},
],
},
{
text: "Internal",
text: "Troubleshooting",
link: "/guide/troubleshooting",
items: [
{
text: "Contributing",
link: "/guide/internal/contributing",
text: "Limitations",
link: "/guide/troubleshooting/limitations",
},
],
},
{
text: "Contributing",
link: "/guide/contributing",
},
],
"/reference": [
{
Expand All @@ -237,7 +248,7 @@ export default defineConfig({
{
text: "Top-Level",
link: "/reference/builder#top-level-attributes",
collapsed: true,
collapsed: false,
items: [
{
text: "builder_type",
Expand Down Expand Up @@ -272,7 +283,7 @@ export default defineConfig({
{
text: "Member",
link: "/reference/builder#member-attributes",
collapsed: true,
collapsed: false,
items: [
{
text: "default",
Expand Down
24 changes: 20 additions & 4 deletions website/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion website/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"medium-zoom": "^1.1.0",
"ts-node": "^10.9.2",
"ts-pattern": "^5.5.0",
"vitepress": "^1.4.5"
"vitepress": "^1.5.0"
},
"dependencies": {
"vue": "^3.5.12"
Expand Down
Loading