From 764e66fe481e80a6bb8d5c1e1ee5a0d0ae4308db Mon Sep 17 00:00:00 2001
From: Veetaha
Date: Thu, 31 Oct 2024 17:56:40 +0000
Subject: [PATCH 01/18] Add completions, update vitepress
---
bon-macros/src/builder/mod.rs | 4 ++--
bon-macros/src/util/ide.rs | 11 ++++++++++-
bon/src/__/ide.rs | 6 ++++++
website/.vitepress/config.mts | 7 ++++---
website/package-lock.json | 8 ++++----
website/package.json | 2 +-
website/tsconfig.json | 6 +++++-
7 files changed, 32 insertions(+), 12 deletions(-)
diff --git a/bon-macros/src/builder/mod.rs b/bon-macros/src/builder/mod.rs
index 2afbede5..8610e6f8 100644
--- a/bon-macros/src/builder/mod.rs
+++ b/bon-macros/src/builder/mod.rs
@@ -30,7 +30,7 @@ pub(crate) fn generate_from_attr(params: TokenStream, item: TokenStream) -> Toke
crate::error::handle_errors(item.clone(), || {
try_generate_from_attr(params.clone(), item)
})
- .unwrap_or_else(|fallback| [generate_completion_triggers(params), fallback].concat())
+ .unwrap_or_else(|fallback| [fallback, generate_completion_triggers(params)].concat())
}
fn try_generate_from_attr(params: TokenStream, item: TokenStream) -> Result {
@@ -72,7 +72,7 @@ fn try_generate_from_attr(params: TokenStream, item: TokenStream) -> Result) -> TokenStream {
CompletionsSchema::leaf("finish_fn"),
CompletionsSchema::leaf("state_mod"),
CompletionsSchema::leaf("on").set_custom_filter(|meta| {
- if !meta.is_empty() {
+ if let Some(first) = meta.first() {
+ if let Meta::Path(path) = first {
+ if path.is_ident("into")
+ || path.is_ident("transparent")
+ || path.is_ident("overwritable")
+ {
+ return;
+ }
+ }
+
meta.remove(0);
}
}),
diff --git a/bon/src/__/ide.rs b/bon/src/__/ide.rs
index 8babac5e..ae649b52 100644
--- a/bon/src/__/ide.rs
+++ b/bon/src/__/ide.rs
@@ -81,6 +81,12 @@ pub mod builder_top_level {
/// See the docs at
pub const into: Flag = Flag;
+
+ /// See the docs at
+ pub const transparent: Flag = Flag;
+
+ /// See the docs at
+ pub const overwritable: Flag = Flag;
}
/// See the docs at
diff --git a/website/.vitepress/config.mts b/website/.vitepress/config.mts
index c6972e62..8f61bcdc 100644
--- a/website/.vitepress/config.mts
+++ b/website/.vitepress/config.mts
@@ -46,6 +46,7 @@ export default defineConfig({
markdown: {
languageAlias: {
+ // Attributes highlighting works with better JS tokenizer 😳
attr: "js",
},
@@ -98,9 +99,9 @@ export default defineConfig({
text: "Edit this page on GitHub",
},
- search: {
- provider: "local",
- },
+ // search: {
+ // provider: "local",
+ // },
nav: [
{ text: "Guide", link: "/guide/overview" },
diff --git a/website/package-lock.json b/website/package-lock.json
index 2d03cda3..bbaecf30 100644
--- a/website/package-lock.json
+++ b/website/package-lock.json
@@ -21,7 +21,7 @@
"smol-toml": "^1.3.0",
"ts-node": "^10.9.2",
"ts-pattern": "^5.5.0",
- "vitepress": "^1.4.2"
+ "vitepress": "^1.4.3"
}
},
"node_modules/@algolia/autocomplete-core": {
@@ -3019,9 +3019,9 @@
}
},
"node_modules/vitepress": {
- "version": "1.4.2",
- "resolved": "https://registry.npmjs.org/vitepress/-/vitepress-1.4.2.tgz",
- "integrity": "sha512-10v92Lqx0N4r7YC3cQLBvu+gRS2rHviE7vgdKiwlupUGfSWkyiQDqYccxM5iPStDGSi1Brnec1lf+lmhaQcZXw==",
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/vitepress/-/vitepress-1.4.3.tgz",
+ "integrity": "sha512-956c2K2Mr0ubY9bTc2lCJD3g0mgo0mARB1iJC/BqUt4s0AM8Wl60wSU4zbFnzV7X2miFK1XJDKzGZnuEN90umw==",
"dev": true,
"dependencies": {
"@docsearch/css": "^3.6.2",
diff --git a/website/package.json b/website/package.json
index 5ac9560d..fd2e3734 100644
--- a/website/package.json
+++ b/website/package.json
@@ -20,7 +20,7 @@
"smol-toml": "^1.3.0",
"ts-node": "^10.9.2",
"ts-pattern": "^5.5.0",
- "vitepress": "^1.4.2"
+ "vitepress": "^1.4.3"
},
"dependencies": {
"vue": "^3.5.12"
diff --git a/website/tsconfig.json b/website/tsconfig.json
index 9d894aca..3fdd435a 100644
--- a/website/tsconfig.json
+++ b/website/tsconfig.json
@@ -1,8 +1,12 @@
{
+ "vueCompilerOptions": {
+ "vitePressExtensions": [".md"],
+ },
"include": [
"**/*.ts",
"**/*.mts",
"**/*.vue",
+ "**/*.md",
".vitepress/**/*.ts",
".vitepress/**/*.vue",
],
@@ -30,5 +34,5 @@
},
"ts-node": {
"esm": true
- }
+ },
}
From 87cf26ef359bd648c9f5b5b1cbc6c7ab13fc63e9 Mon Sep 17 00:00:00 2001
From: Veetaha
Date: Thu, 31 Oct 2024 17:59:04 +0000
Subject: [PATCH 02/18] Revert reordering of completion triggers
---
bon-macros/src/builder/mod.rs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/bon-macros/src/builder/mod.rs b/bon-macros/src/builder/mod.rs
index 8610e6f8..2afbede5 100644
--- a/bon-macros/src/builder/mod.rs
+++ b/bon-macros/src/builder/mod.rs
@@ -30,7 +30,7 @@ pub(crate) fn generate_from_attr(params: TokenStream, item: TokenStream) -> Toke
crate::error::handle_errors(item.clone(), || {
try_generate_from_attr(params.clone(), item)
})
- .unwrap_or_else(|fallback| [fallback, generate_completion_triggers(params)].concat())
+ .unwrap_or_else(|fallback| [generate_completion_triggers(params), fallback].concat())
}
fn try_generate_from_attr(params: TokenStream, item: TokenStream) -> Result {
@@ -72,7 +72,7 @@ fn try_generate_from_attr(params: TokenStream, item: TokenStream) -> Result
Date: Sat, 2 Nov 2024 03:00:15 +0000
Subject: [PATCH 03/18] bon v3 docs (part 2)
---
.../builder/builder_gen/member/config/mod.rs | 2 +-
website/.vitepress/config.mts | 39 +--
.../{ => advanced}/builder-extensions.md | 0
.../guide/{ => basics}/customizing-setters.md | 0
website/src/guide/{ => basics}/documenting.md | 0
website/src/guide/{ => basics}/inspecting.md | 0
.../guide/{ => basics}/optional-members.md | 7 +-
.../guide/{ => basics}/positional-members.md | 0
website/src/guide/overview.md | 14 +-
.../guide/patterns/conditional-building.md | 8 +-
.../guide/patterns/shared-configuration.md | 21 +-
website/src/reference/builder.md | 4 +-
.../src/reference/builder/member/default.md | 234 ++++++++++--------
.../src/reference/builder/member/finish-fn.md | 109 --------
.../src/reference/builder/member/finish_fn.md | 115 +++++++++
website/src/reference/builder/member/into.md | 7 +-
website/src/reference/builder/member/name.md | 8 +-
.../reference/builder/member/overwritable.md | 6 +-
.../src/reference/builder/member/setters.md | 2 +
website/src/reference/builder/member/skip.md | 30 +--
.../src/reference/builder/member/start-fn.md | 106 --------
.../src/reference/builder/member/start_fn.md | 115 +++++++++
.../reference/builder/member/transparent.md | 27 +-
website/src/reference/builder/member/with.md | 2 +
.../{builder-type.md => builder_type.md} | 0
.../top-level/{finish-fn.md => finish_fn.md} | 0
.../top-level/{start-fn.md => start_fn.md} | 0
.../top-level/{state-mod.md => state_mod.md} | 0
28 files changed, 471 insertions(+), 385 deletions(-)
rename website/src/guide/{ => advanced}/builder-extensions.md (100%)
rename website/src/guide/{ => basics}/customizing-setters.md (100%)
rename website/src/guide/{ => basics}/documenting.md (100%)
rename website/src/guide/{ => basics}/inspecting.md (100%)
rename website/src/guide/{ => basics}/optional-members.md (96%)
rename website/src/guide/{ => basics}/positional-members.md (100%)
delete mode 100644 website/src/reference/builder/member/finish-fn.md
create mode 100644 website/src/reference/builder/member/finish_fn.md
delete mode 100644 website/src/reference/builder/member/start-fn.md
create mode 100644 website/src/reference/builder/member/start_fn.md
rename website/src/reference/builder/top-level/{builder-type.md => builder_type.md} (100%)
rename website/src/reference/builder/top-level/{finish-fn.md => finish_fn.md} (100%)
rename website/src/reference/builder/top-level/{start-fn.md => start_fn.md} (100%)
rename website/src/reference/builder/top-level/{state-mod.md => state_mod.md} (100%)
diff --git a/bon-macros/src/builder/builder_gen/member/config/mod.rs b/bon-macros/src/builder/builder_gen/member/config/mod.rs
index 033774da..ebe0455d 100644
--- a/bon-macros/src/builder/builder_gen/member/config/mod.rs
+++ b/bon-macros/src/builder/builder_gen/member/config/mod.rs
@@ -20,7 +20,7 @@ pub(crate) struct MemberConfig {
/// Assign a default value to the member it it's not specified.
///
/// An optional expression can be provided to set the value for the member,
- /// otherwise its [`Default`] trait impl will be used.
+ /// otherwise its [`Default`] trait impl will be used.
#[darling(with = parse_optional_expr, map = Some)]
pub(crate) default: Option>>,
diff --git a/website/.vitepress/config.mts b/website/.vitepress/config.mts
index 8f61bcdc..1650d5de 100644
--- a/website/.vitepress/config.mts
+++ b/website/.vitepress/config.mts
@@ -99,9 +99,13 @@ export default defineConfig({
text: "Edit this page on GitHub",
},
- // search: {
- // provider: "local",
- // },
+ // Enable the search only in the final build on CI. Locally, it takes additional
+ // time during the dev HMR server startup and config reloads.
+ search: !process.env.CI
+ ? undefined
+ : {
+ provider: "local",
+ },
nav: [
{ text: "Guide", link: "/guide/overview" },
@@ -121,12 +125,12 @@ export default defineConfig({
...v2.sidebars,
"/guide": [
{
- text: "Guide",
+ text: "Overview",
+ link: "/guide/overview",
+ },
+ {
+ text: "Basics",
items: [
- {
- text: "Overview",
- link: "/guide/overview",
- },
{
text: "Optional Members",
link: "/guide/optional-members",
@@ -147,10 +151,15 @@ export default defineConfig({
text: "Documenting",
link: "/guide/documenting",
},
+ ],
+ },
+ {
+ text: "Advanced",
+ items: [
{
text: "Builder Extensions",
link: "/guide/builder-extensions",
- }
+ },
]
},
{
@@ -221,7 +230,7 @@ export default defineConfig({
items: [
{
text: "builder_type",
- link: "/reference/builder/top-level/builder-type",
+ link: "/reference/builder/top-level/builder_type",
},
{
text: "crate",
@@ -233,7 +242,7 @@ export default defineConfig({
},
{
text: "finish_fn",
- link: "/reference/builder/top-level/finish-fn",
+ link: "/reference/builder/top-level/finish_fn",
},
{
text: "on",
@@ -241,11 +250,11 @@ export default defineConfig({
},
{
text: "start_fn",
- link: "/reference/builder/top-level/start-fn",
+ link: "/reference/builder/top-level/start_fn",
},
{
text: "state_mod",
- link: "/reference/builder/top-level/state-mod",
+ link: "/reference/builder/top-level/state_mod",
},
],
},
@@ -260,7 +269,7 @@ export default defineConfig({
},
{
text: "finish_fn",
- link: "/reference/builder/member/finish-fn",
+ link: "/reference/builder/member/finish_fn",
},
{
text: "into",
@@ -284,7 +293,7 @@ export default defineConfig({
},
{
text: "start_fn",
- link: "/reference/builder/member/start-fn",
+ link: "/reference/builder/member/start_fn",
},
{
text: "transparent",
diff --git a/website/src/guide/builder-extensions.md b/website/src/guide/advanced/builder-extensions.md
similarity index 100%
rename from website/src/guide/builder-extensions.md
rename to website/src/guide/advanced/builder-extensions.md
diff --git a/website/src/guide/customizing-setters.md b/website/src/guide/basics/customizing-setters.md
similarity index 100%
rename from website/src/guide/customizing-setters.md
rename to website/src/guide/basics/customizing-setters.md
diff --git a/website/src/guide/documenting.md b/website/src/guide/basics/documenting.md
similarity index 100%
rename from website/src/guide/documenting.md
rename to website/src/guide/basics/documenting.md
diff --git a/website/src/guide/inspecting.md b/website/src/guide/basics/inspecting.md
similarity index 100%
rename from website/src/guide/inspecting.md
rename to website/src/guide/basics/inspecting.md
diff --git a/website/src/guide/optional-members.md b/website/src/guide/basics/optional-members.md
similarity index 96%
rename from website/src/guide/optional-members.md
rename to website/src/guide/basics/optional-members.md
index 1294e2c4..8aeee6fd 100644
--- a/website/src/guide/optional-members.md
+++ b/website/src/guide/basics/optional-members.md
@@ -77,8 +77,6 @@ Switching between `#[builder(default)]` and `Option` is [compatible](./compat
:::
-### Examples
-
```rust
#[bon::builder]
fn example(
@@ -105,8 +103,9 @@ The same [pair of optional setters](#setters-pair) is generated for members with
let result = example()
// Pass a non-None value
.a(3)
- // Pass an `Option` value directly
- .maybe_b(Some(5))
+ // Pass an `Option` value directly. `None` means the default
+ // value will be used (4 in this case)
+ .maybe_b(None)
.call();
```
diff --git a/website/src/guide/positional-members.md b/website/src/guide/basics/positional-members.md
similarity index 100%
rename from website/src/guide/positional-members.md
rename to website/src/guide/basics/positional-members.md
diff --git a/website/src/guide/overview.md b/website/src/guide/overview.md
index 8cde4882..7a39b095 100644
--- a/website/src/guide/overview.md
+++ b/website/src/guide/overview.md
@@ -12,7 +12,7 @@ if (versionWildcard == null) {
`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.
-If you are new to the concept of builders or named function arguments, and you don't know what problems they may solve for you, then check out the motivational [blog post](../blog/how-to-do-named-function-arguments-in-rust).
+If you are new to the concept of builders or named function arguments, and you don't know what problems they may solve for you, then check out the [motivational blog post](../blog/how-to-do-named-function-arguments-in-rust).
## Installation
@@ -164,7 +164,7 @@ In general, both `#[derive(Builder)]` on structs and `#[builder]` on functions/m
## No panics possible
-The builders generated by `#[builder]` and `#[derive(Builder)]` use the typestate pattern to make sure all required parameters are filled, and the same setters aren't called repeatedly to prevent unintentional overwrites and typos. If something is wrong, a compile error will be created. There are no potential panics and `unwrap()`s involved.
+The builders generated by `bon`'s macros use the typestate pattern to make sure all required parameters are filled, and the same setters aren't called repeatedly to prevent unintentional overwrites and typos. If something is wrong, a compile error will be created. There are no potential panics and `unwrap()`s involved.
## `Option` values are optional
@@ -176,7 +176,7 @@ It also generates two setters: one accepts `T` and the other accepts `Option`
use bon::Builder;
#[derive(Builder)]
-struct Projection {
+struct Example {
x: Option,
y: Option,
@@ -186,12 +186,12 @@ struct Projection {
}
// Both `x` and `y` will be set to `None`, `z` will be set to `0`
-Projection::builder().build();
+Example::builder().build();
-Projection::builder()
+Example::builder()
// Pass the value without wrapping it with `Some()`
.x(10)
- // Or use a `maybe_`-prefixed setter that accepts `Option`
+ // Or use a `maybe_`-prefixed setter that accepts `Option`
.maybe_y(Some(20))
// The APIs generated for `#[builder(default)]` and `Option` are equivalent.
// `z` will be set to `0` when `build()` is called.
@@ -264,7 +264,7 @@ If you like the idea of this crate and want to say "thank you" or "keep up doing
:::
-This is just part of what's available in `bon`. You may consider reading the rest of the `Guide` section to harness the full power of `bon` and understand the decisions it makes.
+This is just part of what's available in `bon`. You may consider reading the `Basics` section to harness the full power of `bon`.
You can also consult the [API reference index](../reference/builder) that describes all available configuration attributes. This guide will cover most of them but not all. Check the short descriptions of available attributes to see if something might be of immediate interest to you.
diff --git a/website/src/guide/patterns/conditional-building.md b/website/src/guide/patterns/conditional-building.md
index bc22bb81..68c72bc6 100644
--- a/website/src/guide/patterns/conditional-building.md
+++ b/website/src/guide/patterns/conditional-building.md
@@ -1,6 +1,8 @@
# Conditional Building
-On this page, we'll review a case when you have multiple branches in your code that need to set different values for different builder members. Since builders generated by `bon` use the type-state pattern and setters consume `self`, it is a bit more complicated for conditional code to use them. But, not until you know the patterns described below 🐱. So let's learn how to write better conditional code 📚.
+On this page, we'll review a case when you have multiple branches in your code that need to set different values for different builder members.
+
+Since builders generated by `bon` use the type-state pattern and setters consume `self`, it is a bit more complicated for conditional code to use them. But, not until you know the patterns described below 🐱. So let's learn how to write better conditional code 📚.
The patterns described here aren't mutually exclusive. You can combine them as you see necessary to keep your code clean.
@@ -102,11 +104,11 @@ let user = User::builder()
.build();
```
-In this case, we create a variable for each conditional member beforehand and initialize them separately, then we just pass the results to the builder. We benefit from the `maybe_` setters for [optional members](./optional-members) such that we can pass the `Option` values directly.
+In this case, we create a variable for each conditional member beforehand and initialize them separately, then we pass the results to the builder. We benefit from the `maybe_` setters for [optional members](./optional-members) such that we can pass the `Option` values directly.
::: tip NOTE
-However, creating separate variables is not strictly required. You can inline the usage of the variables in such a simple code like here, where each branch of the `if` takes a single line. Anyhow, branches can be much bigger in real code.
+Creating separate variables is not strictly required. You can inline the usages of variables in such a simple code like here, where each branch of the `if` takes a single line. Anyhow, branches can be much bigger in real code.
:::
diff --git a/website/src/guide/patterns/shared-configuration.md b/website/src/guide/patterns/shared-configuration.md
index c169d47a..57c4b2c9 100644
--- a/website/src/guide/patterns/shared-configuration.md
+++ b/website/src/guide/patterns/shared-configuration.md
@@ -8,7 +8,9 @@ On this page, you'll learn how to share common configurations for builders to av
## Problem statement
-As an example, let's suppose you want to enable [`Into` conversions](./into-conversions-in-depth) for specific types across all your builders and maybe also override the name of the finishing function that consumes the builder from the default `build` to `finish`. The problem that you'll quickly run into is that you'll need to repeat the same configuration everywhere:
+As an example, let's suppose you want to enable [`Into` conversions](./into-conversions-in-depth) for specific types across all your builders and maybe also override the name of the finishing function that consumes the builder from the default `build` to `finish`.
+
+The problem that you'll quickly run into is that you'll need to repeat the same configuration for every usage of the builder macro.
```rust
use bon::Builder;
@@ -37,21 +39,19 @@ This code uses the [`#[builder(on(...))]`](../reference/builder/top-level/on) at
:::
-The annoying thing here is that we need to copy all these configurations on every struct where we derive the builder.
-
## Solution
-### Structs
+To overcome this problem you can utilize the [`macro_rules_attribute`] crate. It allows you to declare an [`attribute_alias`](https://docs.rs/macro_rules_attribute/latest/macro_rules_attribute/macro.attribute_alias.html) that defines all the shared configuration for your builders and makes it reusable.
-To overcome this problem we can utilize the [`macro_rules_attribute`] crate. It allows you to declare an [`attribute_alias`](https://docs.rs/macro_rules_attribute/latest/macro_rules_attribute/macro.attribute_alias.html) that defines all the shared configuration for your builders and makes it reusable.
+Use this approach if you have a lot of structs/functions in your crate that need a builder
-So with the [`macro_rules_attribute`] your code will look like this:
+### Structs
```rust
use macro_rules_attribute::{attribute_alias, apply};
// The alias can also be defined in a separate module.
-// Under the hood it creates a macro with `pub(crate)` visibility.
+// Under the hood, it creates a macro with `pub(crate)` visibility.
attribute_alias! {
#[apply(derive_builder!)] =
#[derive(::bon::Builder)]
@@ -69,13 +69,8 @@ struct MyLovelyStruct1 { /**/ }
struct MyLovelyStruct2 { /**/ }
```
-Use this approach if you have a lot of structs in your crate that need a builder. Adding [`macro_rules_attribute`] to your dependencies shouldn't have a noticeable impact on the compilation performance. This approach [was tested](https://github.com/ayrat555/frankenstein/blob/91ac379a52ed716e09632f78b984852c85f2adaa/src/macros.rs#L3-L14) on a crate with ~320 structs that derive a builder and compile time was the same as before adding the [`macro_rules_attribute`] crate.
-
### Free functions
-A similar approach works with `#[bon::builder]` on free functions.
-**Example:**
-
```rust
use macro_rules_attribute::{attribute_alias, apply};
@@ -100,6 +95,6 @@ fn my_lovely_fn2(/**/) { /**/ }
Unfortunately, this technique doesn't quite work with associated methods (functions inside impl blocks) due to the limitations of proc macro attribute expansion order. The `#[bon]` macro on top of the impl block is expanded first before the `#[apply(...)]` macro inside of the impl block, so `#[bon]` doesn't see the configuration expanded from the `#[apply(...)]`.
-There is a proposed solution to this problem in the issue [#elastio/bon#144](https://github.com/elastio/bon/issues/144). Add a 👍 to that issue if your use case needs a solution for this, and maybe leave a comment about your particular use case where you'd like to have this feature.
+There is a proposed solution to this problem in the issue [#144](https://github.com/elastio/bon/issues/144). Add a 👍 to that issue if your use case needs a solution for this. It would be even better if you left a comment describing your particular use case where you'd like to have this feature.
[`macro_rules_attribute`]: https://docs.rs/macro_rules_attribute/latest/macro_rules_attribute/
diff --git a/website/src/reference/builder.md b/website/src/reference/builder.md
index 36e85b52..3acc2e95 100644
--- a/website/src/reference/builder.md
+++ b/website/src/reference/builder.md
@@ -29,11 +29,11 @@ These attributes are placed on a `struct` field or `fn` argument.
| [`finish_fn`](./builder/member/finish-fn) | Makes the member a positional argument on the finishing function
| [`into`](./builder/member/into) | Changes the signature of the setters to accept `impl Into`
| [`name`](./builder/member/name) | Overrides the name of the member used in the builder's API
-| [`overwritable` 🔬](./builder/member/overwritable) | Lets calling setters for the same member repeatedly
+| [`overwritable` 🔬](./builder/member/overwritable) | Allows calling setters for the same member repeatedly
| [`setters`](./builder/member/setters) | Overrides name, visibility and docs for setters
| [`skip`](./builder/member/skip) | Skips generating setters for the member
| [`start_fn`](./builder/member/start-fn) | Makes the member a positional argument on the starting function
-| [`transparent`](./builder/member/transparent) | ??????? TODO: ADD DOCS ??????
+| [`transparent`](./builder/member/transparent) | Disables `Option` special handling, makes the member required
| [`with`](./builder/member/with) | ??????? TODO: ADD DOCS ??????
## Examples
diff --git a/website/src/reference/builder/member/default.md b/website/src/reference/builder/member/default.md
index ffd1c7e0..53f2800c 100644
--- a/website/src/reference/builder/member/default.md
+++ b/website/src/reference/builder/member/default.md
@@ -2,174 +2,208 @@
**Applies to:**
-Makes the member optional and assigns a default value to it. There will be two setter methods generated for the member just like for [members of type `Option`](../../../guide/optional-members). One setter accepts a value of type `T` (type of the member) and the other (with the `maybe_` prefix) accepts an `Option`.
+Makes the member optional and assigns a default value to it. The default value is lazily computed inside of the finishing function based on the form of this attribute.
-::: tip
+## Syntax
-Switching between `#[builder(default)]` and `Option` is [compatible](../../../guide/compatibility#switching-between-option-t-and-builder-default).
+| Form | How default value is computed
+| -----------------------------------------|-------------------------------
+| `#[builder(default)]` | `Default::default()`
+| `#[builder(default = expression)]` | `expression`
-:::
+If combined with [`#[builder(into)]`](./into), the default expression is additionally converted via [`Into::into`](https://doc.rust-lang.org/stable/std/convert/trait.Into.html).
+
+## Setters
+
+Two setter methods are generated for the member with `#[builder(default)]` just like for [members of type `Option`](../../../guide/optional-members#setters-pair):
+
+| Name | Input | Description | Configuration attribute
+|------------------|-------------|-------------------------------|------------------
+| `{member}` | `T` | Accepts a non-`None` value. | [`some_fn`](./setters)
+| `maybe_{member}` | `Option` | Accepts an `Option` directly. | [`option_fn`](./setters)
-The default value will be lazily computed inside of the [finishing function](./finish-fn) (i.e. `build()` or `call()`). It is computed only if the setter for the member wasn't called or `None` was passed to the `maybe_{member}()` setter.
+If `None` is passed to the `maybe_{member}` setter, then the default value is used.
-The default value is computed based on the form of this attribute:
+::: tip
-| Form | How default value is computed |
-| ---------------------------------- | ----------------------------- |
-| `#[builder(default)]` | `Default::default()` |
-| `#[builder(default = expression)]` | `expression` |
+Switching between `#[builder(default)]` and `Option` is [compatible](../../../guide/compatibility#switching-between-option-t-and-builder-default).
-The result of the `expression` will be converted into the target type using [`Into::into`](https://doc.rust-lang.org/stable/std/convert/trait.Into.html) if [`#[builder(into)]`](./into) is enabled for the setter.
+:::
-**Example:**
::: code-group
-```rust [Struct field]
+```rust [Struct]
use bon::Builder;
#[derive(Builder)]
-struct User {
+struct Example {
#[builder(default)] // [!code highlight]
- level: u32,
+ foo: u32,
- // The expression of type `&'static str` is automatically // [!code highlight]
- // converted to `String` here via `Into` thanks to `#[builder(into)]. // [!code highlight]
- #[builder(into, default = "anon")] // [!code highlight]
- name: String,
+ #[builder(default = "anon".to_owned())] // [!code highlight]
+ bar: String,
- // Any complex expression is accepted // [!code highlight]
- #[builder(default = bon::vec!["read"])] // [!code highlight]
- permissions: Vec,
+ // No need for `.to_owned()`. Into is applied to the expression
+ #[builder(default = "bon", into)] // [!code highlight]
+ baz: String,
}
-let user = User::builder().build();
+let value = Example::builder().build();
+
+assert_eq!(value.foo, 0);
+assert_eq!(value.bar, "anon");
+assert_eq!(value.baz, "bon");
+
+let value = Example::builder()
+ .foo(99)
+ .maybe_bar(None) // None means the default will be used
+ .maybe_baz(Some("lyra"))
+ .build();
-assert_eq!(user.level, 0);
-assert_eq!(user.name, "anon");
-assert_eq!(user.permissions, ["read"]);
+assert_eq!(value.foo, 99);
+assert_eq!(value.bar, "anon");
+assert_eq!(value.baz, "lyra");
```
-```rust [Free function argument]
+```rust [Free function]
use bon::builder;
#[builder]
-fn greet_user(
+fn example(
#[builder(default)] // [!code highlight]
- level: u32,
-
- // The expression of type `&'static str` is automatically // [!code highlight]
- // converted to `String` here via `Into` thanks to `#[builder(into)]. // [!code highlight]
- #[builder(into, default = "anon")] // [!code highlight]
- name: String,
-
- // Any complex expression is accepted // [!code highlight]
- #[builder(default = bon::vec!["read"])] // [!code highlight]
- permissions: Vec,
-) -> String {
- format!("Hello {name}! Your level is {level}, permissions: {permissions:?}")
+ foo: u32,
+
+ #[builder(default = "anon".to_owned())] // [!code highlight]
+ bar: String,
+
+ // No need for `.to_owned()`. Into is applied to the expression
+ #[builder(default = "bon", into)] // [!code highlight]
+ baz: String,
+) -> (u32, String, String) {
+ (foo, bar, baz)
}
-let greeting = greet_user().call();
+let value = example().call();
+
+assert_eq!(value.0, 0);
+assert_eq!(value.1, "anon");
+assert_eq!(value.2, "bon");
+
+let value = example()
+ .foo(99)
+ .maybe_bar(None) // None means the default will be used
+ .maybe_baz(Some("lyra"))
+ .call();
-assert_eq!(greeting, "Hello anon! Your level is 0, permissions: [\"read\"]");
+assert_eq!(value.0, 99);
+assert_eq!(value.1, "anon");
+assert_eq!(value.2, "lyra");
```
-```rust [Associated method argument]
+```rust [Associated method]
use bon::bon;
-struct User {
- level: u32,
- name: String,
- permissions: Vec,
+struct Example {
+ foo: u32,
+ bar: String,
+ baz: String,
}
#[bon]
-impl User {
+impl Example {
#[builder]
fn new(
#[builder(default)] // [!code highlight]
- level: u32,
+ foo: u32,
- // The expression of type `&'static str` is automatically // [!code highlight]
- // converted to `String` here via `Into` thanks to `#[builder(into)]. // [!code highlight]
- #[builder(into, default = "anon")] // [!code highlight]
- name: String,
+ #[builder(default = "anon".to_owned())] // [!code highlight]
+ bar: String,
- // Any complex expression is accepted // [!code highlight]
- #[builder(default = bon::vec!["read"])] // [!code highlight]
- permissions: Vec,
+ // No need for `.to_owned()`. Into is applied to the expression
+ #[builder(default = "bon", into)] // [!code highlight]
+ baz: String,
) -> Self {
- Self { level, name, permissions }
+ Self { foo, bar, baz }
}
}
-let user = User::builder().build();
+let value = Example::builder().build();
+
+assert_eq!(value.foo, 0);
+assert_eq!(value.bar, "anon");
+assert_eq!(value.baz, "bon");
+
+let value = Example::builder()
+ .foo(99)
+ .maybe_bar(None) // None means the default will be used
+ .maybe_baz(Some("lyra"))
+ .build();
-assert_eq!(user.name, "anon");
-assert_eq!(user.level, 0);
-assert_eq!(user.permissions, ["read"]);
+assert_eq!(value.foo, 99);
+assert_eq!(value.bar, "anon");
+assert_eq!(value.baz, "lyra");
```
:::
-You can also use the values of other members by referencing their names in the `default` expression. All members are initialized in the order of their declaration. It means only those members that are declared earlier (higher) in the code are available to the `default` expression.
+## Evaluation context
-**Example:**
+You can use the values of other members by referencing their names in the `default` expression. All members are initialized in the order of their declaration. It means only those members that are declared earlier (higher) in the code are available to the `default` expression.
::: code-group
-```rust [Struct field]
+```rust [Struct]
use bon::Builder;
#[derive(Builder)]
struct Example {
- member_1: u32,
+ foo: u32,
- // Note that here we don't have access to `member_3`
+ // Note that here we don't have access to `baz`
// because it's declared (and thus initialized) later
- #[builder(default = 2 * member_1)]
- member_2: u32,
+ #[builder(default = 2 * foo)]
+ bar: u32,
- #[builder(default = member_2 + member_1)]
- member_3: u32,
+ #[builder(default = bar + foo)]
+ baz: u32,
}
-let example = Example::builder()
- .member_1(3)
+let value = Example::builder()
+ .foo(3)
.build();
-assert_eq!(example.member_1, 3);
-assert_eq!(example.member_2, 6);
-assert_eq!(example.member_3, 9);
+assert_eq!(value.foo, 3);
+assert_eq!(value.bar, 6);
+assert_eq!(value.baz, 9);
```
-```rust [Free function argument]
+```rust [Free function]
use bon::builder;
#[builder]
fn example(
- member_1: u32,
+ foo: u32,
- // Note that here we don't have access to `member_3`
+ // Note that here we don't have access to `baz`
// because it's declared (and thus initialized) later
- #[builder(default = 2 * member_1)]
- member_2: u32,
+ #[builder(default = 2 * foo)]
+ bar: u32,
- #[builder(default = member_2 + member_1)]
- member_3: u32,
+ #[builder(default = bar + foo)]
+ baz: u32,
) -> (u32, u32, u32) {
- (member_1, member_2, member_3)
+ (foo, bar, baz)
}
-let example = example()
- .member_1(3)
+let value = example()
+ .foo(3)
.call();
-assert_eq!(example, (3, 6, 9));
+assert_eq!(value, (3, 6, 9));
```
-```rust [Associated method argument]
+```rust [Associated method]
use bon::bon;
struct Example;
@@ -178,33 +212,33 @@ struct Example;
impl Example {
#[builder]
fn example(
- member_1: u32,
+ foo: u32,
- // Note that here we don't have access to `member_3`
+ // Note that here we don't have access to `baz`
// because it's declared (and thus initialized) later
- #[builder(default = 2 * member_1)]
- member_2: u32,
+ #[builder(default = 2 * foo)]
+ bar: u32,
- #[builder(default = member_2 + member_1)]
- member_3: u32,
+ #[builder(default = bar + foo)]
+ baz: u32,
) -> (u32, u32, u32) {
- (member_1, member_2, member_3)
+ (foo, bar, baz)
}
}
-let example = Example::example()
- .member_1(3)
+let value = Example::example()
+ .foo(3)
.call();
-assert_eq!(example, (3, 6, 9));
+assert_eq!(value, (3, 6, 9));
```
:::
-## Caveats
+### Caveats
-The `self` parameter in associated methods is not available to the `default` expression. If you need the `self` context for your defaulting logic, then set your member's type to `Option` and handle the defaulting in the function's body manually.
+The `self` parameter in associated method syntax is not available to the `default` expression. If you need the `self` context for your defaulting logic, then set your member's type to `Option` and handle the defaulting in the function's body manually.
## Compile errors
-This attribute is incompatible with members of `Option` type, since `Option` already implies the default value of `None`.
+This attribute is incompatible with members of `Option` type, since `Option` already implies the default value of `None`. However, it can be used together with [`#[builder(transparent)]`](./transparent).
diff --git a/website/src/reference/builder/member/finish-fn.md b/website/src/reference/builder/member/finish-fn.md
deleted file mode 100644
index e572f37e..00000000
--- a/website/src/reference/builder/member/finish-fn.md
+++ /dev/null
@@ -1,109 +0,0 @@
-
-# `finish_fn`
-
-**Applies to:**
-
-Makes the member a positional argument on the finishing function that consumes the builder and returns the resulting object (for struct syntax) or performs the requested action (for function/method syntax).
-
-The ordering of members annotated with `#[builder(finish_fn)]` matters! They will appear in the same order relative to each other in the finishing function signature. They must also be declared at the top of the members list strictly after members annotated with [`#[builder(start_fn)]`](./start-fn) (if any).
-
-This ensures a consistent initialization order, and it makes these members available for expressions in `#[builder(default/skip = ...)]` for regular members that follow them.
-
-::: tip
-
-Don't confuse this with the top-level [`#[builder(finish_fn = ...)]`](../top-level/finish-fn) attribute that can be used to configure the name, visibility and docs of the finishing function. You'll likely want to use it in combination with this member-level attribute to define a better name for the finishing function.
-
-:::
-
-**Example:**
-
-::: code-group
-
-```rust [Struct field]
-use bon::Builder;
-
-#[derive(Builder)]
-// Top-level attribute to give a better name for the finishing function // [!code highlight]
-#[builder(finish_fn = sign)] // [!code highlight]
-struct Message {
- // Member-level attribute to mark the member as a parameter of `sign()` // [!code highlight]
- #[builder(finish_fn)] // [!code highlight]
- author_first_name: String,
-
- #[builder(finish_fn)] // [!code highlight]
- author_last_name: String,
-
- payload: String,
-}
-
-let message = Message::builder()
- .payload("Bon is great! Give it a ⭐".to_owned())
- .sign("Sweetie".to_owned(), "Drops".to_owned());
-
-assert_eq!(message.payload, "Bon is great! Give it a ⭐");
-assert_eq!(message.author_first_name, "Sweetie");
-assert_eq!(message.author_last_name, "Drops");
-```
-
-```rust [Free function]
-use bon::builder;
-
-// Top-level attribute to give a better name for the finishing function // [!code highlight]
-#[builder(finish_fn = send)] // [!code highlight]
-fn message(
- // Member-level attribute to mark the member as a parameter of `sign()` // [!code highlight]
- #[builder(finish_fn)] // [!code highlight]
- receiver_first_name: String,
-
- #[builder(finish_fn)] // [!code highlight]
- receiver_last_name: String,
-
- payload: String,
-) {}
-
-message()
- .payload("Bon is great! Give it a ⭐".to_owned())
- .send("Sweetie".to_owned(), "Drops".to_owned());
-```
-
-```rust [Associated method]
-use bon::bon;
-
-struct Chat {}
-
-#[bon]
-impl Chat {
- // Top-level attribute to give a better name for the finishing function // [!code highlight]
- #[builder(finish_fn = send)] // [!code highlight]
- fn message(
- &self,
-
- // Member-level attribute to mark the member as a parameter of `sign()` // [!code highlight]
- #[builder(finish_fn)] // [!code highlight]
- receiver_first_name: String,
-
- #[builder(finish_fn)] // [!code highlight]
- receiver_last_name: String,
-
- payload: String,
- ) {}
-}
-
-let chat = Chat {};
-
-chat.message()
- .payload("Bon is great! Give it a ⭐".to_owned())
- .send("Sweetie".to_owned(), "Drops".to_owned());
-```
-
-:::
-
-You can also combine this attribute with [`#[builder(into)]`](./into) or [`#[builder(on(..., into))]`](../top-level/on) to add an into conversion for the parameter.
-
-Importantly, `Into` conversions for such members work slightly differently from the regular (named) members in regard to the `Option` type. The `Option` type gives no additional meaning to the member annotated with `#[builder(finish_fn)]`. Thus, it is matched by the type pattern of `on(..., into)` and wrapped with `impl Into
-`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.
+
+
+| Resource | Description
+| -- | -- |
+| [📖 Guide Book](https://bon-rs.com/guide/overview) |Narrative introduction
+| [🔍 API Reference](https://bon-rs.com/reference/builder) | Attributes API index
+
+
-Visit the [guide for a complete overview of the crate](https://bon-rs.com/guide/overview).
+## Overview
+
+`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.
-## Quick examples
+If you wonder "Why would I use builders?", see the [motivational blog post](https://bon-rs.com/blog/how-to-do-named-function-arguments-in-rust).
-### Builder for a free function
+## Function Builder
-You can turn a function with positional parameters into a function with named parameters just by placing the `#[builder]` attribute on top of it.
+You can turn a function with positional parameters into a function with named parameters just by placing `#[builder]` on top of it.
```rust
use bon::builder;
@@ -60,9 +69,13 @@ let greeting = greet()
assert_eq!(greeting, "Hello Bon! Your level is 24");
```
-### Builder for an associated method
+Any syntax for functions is supported including `async`, fallible, generic functions, `impl Trait`, etc.
-For associated methods you also need to add the `#[bon]` macro on top of the impl block.
+## Method Builder
+
+Associated methods require `#[bon]` on top of the impl block.
+
+The method named `new` generates `builder()/build()` methods.
```rust
use bon::bon;
@@ -72,41 +85,49 @@ struct User {
name: String,
}
-#[bon] // <- this attribute is required on impl blocks that contain `#[builder]`
+#[bon]
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
+assert_eq!(user.id, 1);
+assert_eq!(user.name, "Bon");
+```
+
+All other methods generate `{method_name}()/call()` methods.
+
+```rust
+#[bon]
+impl User {
+ #[builder]
+ fn greet(&self, target: &str, prefix: Option<&str>) -> String {
+ let prefix = prefix.unwrap_or("INFO");
+ let name = &self.name;
+
+ format!("[{prefix}] {name} says hello to {target}")
+ }
+}
+
let greeting = user
.greet()
.target("the world")
- // `level` is optional, we can omit it here
+ // `prefix` 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
+Methods with or without `self` are both supported.
+
+## Struct Builder
The `#[derive(Builder)]` macro generates a builder for a struct.
@@ -133,11 +154,32 @@ assert_eq!(user.level, Some(24));
assert!(user.is_admin);
```
-See [the guide](https://bon-rs.com/guide/overview) for more.
+## No Panics Possible
+
+The builders generated by `bon`'s macros use the typestate pattern to make sure 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.
+
+
+| ⭐ 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). You can continue reading [next page](https://bon-rs.com/guide/optional-members). Knowledge is power 🚀!
+
+The [🔍 API Reference](https://bon-rs.com/reference/builder) will help you navigate in the attributes once you feel comfortable with the basics of `bon`.
+
+## Installation
+
+Add this to your `Cargo.toml` to use this crate:
+
+```toml-vue
+[dependencies]
+bon = "2.3"
+```
-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](https://github.com/elastio/bon). Any support and contribution are appreciated 🐱!
+You can opt out of `std` and `alloc` cargo features with `default-features = false` for `no_std` environments.
#### License
diff --git a/bon-macros/src/builder/builder_gen/mod.rs b/bon-macros/src/builder/builder_gen/mod.rs
index db1b5b11..a90f263c 100644
--- a/bon-macros/src/builder/builder_gen/mod.rs
+++ b/bon-macros/src/builder/builder_gen/mod.rs
@@ -368,7 +368,7 @@ impl BuilderGenCtx {
if you found yourself needing it, then you are probably doing something wrong; \
feel free to open an issue/discussion in our GitHub repository \
(https://github.com/elastio/bon) or ask for help in our Discord server \
- (https://discord.gg/QcBYSamw4c)";
+ (https://bon-rs.com/discord)";
quote! {
#[doc(hidden)]
diff --git a/bon/Cargo.toml b/bon/Cargo.toml
index 84a88077..71f42c6a 100644
--- a/bon/Cargo.toml
+++ b/bon/Cargo.toml
@@ -14,7 +14,7 @@ categories = [
keywords = ["builder", "macro", "derive", "constructor", "setter"]
edition = "2021"
-homepage = "https://bon-rs.com/"
+homepage = "https://bon-rs.com"
license = "MIT OR Apache-2.0"
repository = "https://github.com/elastio/bon"
diff --git a/bon/src/lib.rs b/bon/src/lib.rs
index 36f6a57c..398a3402 100644
--- a/bon/src/lib.rs
+++ b/bon/src/lib.rs
@@ -22,7 +22,7 @@ mod collections;
they should not be used directly; if you found a need for this, then you are probably \
doing something wrong; feel free to open an issue/discussion in our GitHub repository \
(https://github.com/elastio/bon) or ask for help in our Discord server \
- (https://discord.gg/QcBYSamw4c)"]
+ (https://bon-rs.com/discord)"]
pub mod __;
mod builder_state;
diff --git a/website/.vitepress/config.mts b/website/.vitepress/config.mts
index 1650d5de..4018786e 100644
--- a/website/.vitepress/config.mts
+++ b/website/.vitepress/config.mts
@@ -116,7 +116,7 @@ export default defineConfig({
socialLinks: [
{ icon: "github", link: "https://github.com/elastio/bon" },
- { icon: "discord", link: "https://discord.gg/QcBYSamw4c" },
+ { icon: "discord", link: "https://bon-rs.com/discord" },
{ icon: "x", link: "https://x.com/veetaha" },
],
@@ -136,8 +136,12 @@ export default defineConfig({
link: "/guide/optional-members",
},
{
- text: "Customizing Setters",
- link: "/guide/customizing-setters",
+ text: "Into Conversions",
+ link: "/guide/into-conversions",
+ },
+ {
+ text: "Custom Conversions",
+ link: "/guide/custom-conversions",
},
{
text: "Positional Members",
diff --git a/website/src/blog/bon-builder-v2-2-release.md b/website/src/blog/bon-builder-v2-2-release.md
index fcd09799..6efebb54 100644
--- a/website/src/blog/bon-builder-v2-2-release.md
+++ b/website/src/blog/bon-builder-v2-2-release.md
@@ -222,7 +222,7 @@ If you like or dislike this change in syntax feel free to write a comment on Red
## Summary
-We are listening to your feedback! If you'd like to propose a change in `bon`, or ask a question, or just say "thank you", consider joining our [newly launched Discord server](https://discord.gg/QcBYSamw4c)!
+We are listening to your feedback! If you'd like to propose a change in `bon`, or ask a question, or just say "thank you", consider joining our [newly launched Discord server](https://bon-rs.com/discord)!
Also, a huge thank you for 750 stars ⭐ [on Github](https://github.com/elastio/bon)! Consider giving [`bon`] a star if you haven't already. Your support and feedback are a big motivation and together we can build a better builder 🐱!
diff --git a/website/src/blog/bon-builder-v2-3-release.md b/website/src/blog/bon-builder-v2-3-release.md
index 9d8447dd..f69c1a3c 100644
--- a/website/src/blog/bon-builder-v2-3-release.md
+++ b/website/src/blog/bon-builder-v2-3-release.md
@@ -143,7 +143,7 @@ This isn't a breaking change, and the code that uses `#[bon::builder]` on a stru
Huge thank you for 925 stars ⭐ [on Github](https://github.com/elastio/bon)! Consider giving [`bon`] a star if you haven't already. Your support and feedback are a big motivation and together we can build a better builder 🐱!
-Bon's goal is to empower everyone to build beautiful APIs with great flexibility and extensibility. If you have any feedback or ideas for improvement consider joining [our Discord server](https://discord.gg/QcBYSamw4c) to discuss them, or just [open an issue on Github](https://github.com/elastio/bon/issues).
+Bon's goal is to empower everyone to build beautiful APIs with great flexibility and extensibility. If you have any feedback or ideas for improvement consider joining [our Discord server](https://bon-rs.com/discord) to discuss them, or just [open an issue on Github](https://github.com/elastio/bon/issues).
::: tip
diff --git a/website/src/guide/basics/custom-conversions.md b/website/src/guide/basics/custom-conversions.md
new file mode 100644
index 00000000..f334e811
--- /dev/null
+++ b/website/src/guide/basics/custom-conversions.md
@@ -0,0 +1 @@
+# Custom Conversions
diff --git a/website/src/guide/basics/customizing-setters.md b/website/src/guide/basics/customizing-setters.md
deleted file mode 100644
index ef8086d2..00000000
--- a/website/src/guide/basics/customizing-setters.md
+++ /dev/null
@@ -1 +0,0 @@
-# Customizing Setters
diff --git a/website/src/guide/basics/into-conversions.md b/website/src/guide/basics/into-conversions.md
new file mode 100644
index 00000000..057f8a8e
--- /dev/null
+++ b/website/src/guide/basics/into-conversions.md
@@ -0,0 +1,52 @@
+# `Into` conversions
+
+If you have members of type `String`, or `PathBuf`, and you need to set them to a hard-coded string literal, then you have to write `.to_owned()` or `.to_string()` or `.into()`.
+
+```rust
+use bon::Builder;
+use std::path::PathBuf;
+
+#[derive(Builder)] // [!code focus]
+struct Project { // [!code focus]
+ name: String, // [!code focus]
+ description: String, // [!code focus]
+ path: PathBuf, // [!code focus]
+} // [!code focus]
+
+Project::builder()
+ .name("Bon".to_owned()) // [!code focus]
+ .description("Awesome crate 🐱".to_string()) // [!code focus]
+ .path("/path/to/bon".into()) // [!code focus]
+ .build();
+```
+
+However, you can ask `bon` to generate setters that accept `impl Into` to remove the need for manual conversion.
+
+This can be configured with [`#[builder(into)]`](../reference/builder/member/into) for a single member or with [`#[builder(on({type}, into))]`](../reference/builder/top-level/on) for many members at once.
+
+```rust
+use bon::Builder;
+use std::path::PathBuf;
+
+// All setters for members of type `String` will accept `impl Into` // [!code highlight]
+#[derive(Builder)] // [!code highlight]
+#[builder(on(String, into))] // [!code highlight]
+struct Project {
+ name: String,
+ description: String,
+
+ // The setter only for this member will accept `impl Into` // [!code highlight]
+ #[builder(into)] // [!code highlight]
+ path: PathBuf,
+}
+
+Project::builder()
+ // &str is converted to `String` internally // [!code highlight]
+ .name("Bon")
+ .description("Awesome crate 🐱")
+ // `&str` is converted to `PathBuf` internally // [!code highlight]
+ .path("/path/to/your/heart")
+ .build();
+```
+
+`Into` conversions don't always make sense, and you should be aware of their downsides as well. The article ["Into Conversions In-Depth"](./into-conversions-in-depth) provides recommendations on when it makes sense to use and to avoid `Into` conversions.
diff --git a/website/src/guide/basics/optional-members.md b/website/src/guide/basics/optional-members.md
index 8aeee6fd..152926b7 100644
--- a/website/src/guide/basics/optional-members.md
+++ b/website/src/guide/basics/optional-members.md
@@ -4,6 +4,39 @@ outline: deep
# Optional Members
+If your function argument or struct field (or member for short) is of type `Option`, then the generated builder will not enforce setting a value for this member, defaulting to `None`.
+
+It also generates two setters: one accepts `T` and the other accepts `Option`. The first avoids wrapping values with `Some()` on the call site. The second allows passing the `Option` value directly.
+
+```rust
+use bon::Builder;
+
+#[derive(Builder)]
+struct Example {
+ x: Option,
+ y: Option,
+
+ // Use an annotation for members of non-`Option` type
+ #[builder(default)]
+ z: u32,
+}
+
+// Both `x` and `y` will be set to `None`, `z` will be set to `0`
+Example::builder().build();
+
+Example::builder()
+ // Pass the value without wrapping it with `Some()`
+ .x(10)
+ // Or use a `maybe_`-prefixed setter that accepts `Option`
+ .maybe_y(Some(20))
+ // The APIs generated for `#[builder(default)]` and `Option` are equivalent.
+ // `z` will be set to `0` when `build()` is called.
+ .maybe_z(None)
+ .build();
+```
+
+See [optional members](./optional-members) page for details.
+
## `Option`
Setters generated for members of `Option` type are optional to call. If they aren't invoked, then `None` will be used as the default.
diff --git a/website/src/guide/overview.md b/website/src/guide/overview.md
index 7a39b095..f6749354 100644
--- a/website/src/guide/overview.md
+++ b/website/src/guide/overview.md
@@ -162,100 +162,6 @@ See [compatibility](./compatibility#switching-between-derive-builder-and-builder
In general, both `#[derive(Builder)]` on structs and `#[builder]` on functions/methods have almost the same API. We'll use both of them throughout the documentation to provide examples. If the example shows only the usage of one syntax (e.g. `#[builder]`), it's very likely that the other syntax (e.g. `#[derive(Builder)]`) works similarly unless explicitly stated otherwise.
-## No panics possible
-
-The builders generated by `bon`'s macros use the typestate pattern to make sure all required parameters are filled, and the same setters aren't called repeatedly to prevent unintentional overwrites and typos. If something is wrong, a compile error will be created. There are no potential panics and `unwrap()`s involved.
-
-## `Option` values are optional
-
-If your function argument or struct field (or member for short) is of type `Option`, then the generated builder will not enforce setting a value for this member, defaulting to `None`.
-
-It also generates two setters: one accepts `T` and the other accepts `Option`. The first avoids wrapping values with `Some()` on the call site. The second allows passing the `Option` value directly.
-
-```rust
-use bon::Builder;
-
-#[derive(Builder)]
-struct Example {
- x: Option,
- y: Option,
-
- // Use an annotation for members of non-`Option` type
- #[builder(default)]
- z: u32,
-}
-
-// Both `x` and `y` will be set to `None`, `z` will be set to `0`
-Example::builder().build();
-
-Example::builder()
- // Pass the value without wrapping it with `Some()`
- .x(10)
- // Or use a `maybe_`-prefixed setter that accepts `Option`
- .maybe_y(Some(20))
- // The APIs generated for `#[builder(default)]` and `Option` are equivalent.
- // `z` will be set to `0` when `build()` is called.
- .maybe_z(None)
- .build();
-```
-
-See [optional members](./optional-members) page for details.
-
-## `Into` conversions
-
-If you have members of type `String`, or `PathBuf`, and you need to set them to a hard-coded string literal, then you have to write `.to_owned()` or `.to_string()` or `.into()`.
-
-**Example:**
-
-```rust
-use bon::Builder;
-use std::path::PathBuf;
-
-#[derive(Builder)] // [!code focus]
-struct Project { // [!code focus]
- name: String, // [!code focus]
- description: String, // [!code focus]
- path: PathBuf, // [!code focus]
-} // [!code focus]
-
-Project::builder()
- .name("Bon".to_owned()) // [!code focus]
- .description("Awesome crate 🐱".to_string()) // [!code focus]
- .path("/path/to/bon".into()) // [!code focus]
- .build();
-```
-
-However, you can ask `bon` to generate setters that accept `impl Into` to remove the need for manual conversion.
-
-This can be configured with [`#[builder(into)]`](../reference/builder/member/into) for a single member or with [`#[builder(on({type}, into))]`](../reference/builder/top-level/on) for many members at once.
-
-```rust
-use bon::Builder;
-use std::path::PathBuf;
-
-// All setters for members of type `String` will accept `impl Into` // [!code highlight]
-#[derive(Builder)] // [!code highlight]
-#[builder(on(String, into))] // [!code highlight]
-struct Project {
- name: String,
- description: String,
-
- // The setter only for this member will accept `impl Into` // [!code highlight]
- #[builder(into)] // [!code highlight]
- path: PathBuf,
-}
-
-Project::builder()
- // &str is converted to `String` internally // [!code highlight]
- .name("Bon")
- .description("Awesome crate 🐱")
- // `&str` is converted to `PathBuf` internally // [!code highlight]
- .path("/path/to/your/heart")
- .build();
-```
-
-See the ["Into Conversions In-Depth"](./into-conversions-in-depth) page for more details and important caveats (!).
-
## What's next?
::: tip
@@ -270,7 +176,7 @@ You can also consult the [API reference index](../reference/builder) that descri
However, feel free to skip the docs and just use the `#[builder]` and `#[derive(Builder)]` in your code. They are designed to be intuitive, so they'll probably do the thing you want them to do already.
-If you can't figure something out, consult the docs and maybe use that search `🔍 Search` thing at the top to navigate. 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://discord.gg/QcBYSamw4c) (see below).
+If you can't figure something out, consult the docs and maybe use that search `🔍 Search` thing at the top to navigate. 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) (see below).
Click the "Next page" button at the bottom to proceed with the guide.
@@ -283,9 +189,9 @@ Click the "Next page" button at the bottom to proceed with the guide.
Here you can leave feedback, ask questions, report bugs, or just write "thank you".
diff --git a/website/src/v2/guide/overview.md b/website/src/v2/guide/overview.md
index 3cc3e501..d8699b4e 100644
--- a/website/src/v2/guide/overview.md
+++ b/website/src/v2/guide/overview.md
@@ -264,7 +264,7 @@ This is just part of what's available in `bon`. You may consider reading the res
However, feel free to skip the docs and just use the `#[builder]` and `#[derive(Builder)]` in your code. They are designed to be intuitive, so they'll probably do the thing you want them to do already.
-If you can't figure something out, consult the docs and maybe use that search `🔍 Search` thing at the top to navigate. You may also create an issue or a discussion in the [Github repository](https://github.com/elastio/bon) for help, or write us a message in [Discord](https://discord.gg/QcBYSamw4c) (see below).
+If you can't figure something out, consult the docs and maybe use that search `🔍 Search` thing at the top to navigate. You may also create an issue or a discussion in the [Github repository](https://github.com/elastio/bon) for help, or write us a message in [Discord](https://bon-rs.com/discord) (see below).
## Socials
@@ -275,9 +275,9 @@ If you can't figure something out, consult the docs and maybe use that search `
Here you can leave feedback, ask questions, report bugs, or just write "thank you".
From a3d3a3ea683558d92607657496e2b52a55a17163 Mon Sep 17 00:00:00 2001
From: Veetaha
Date: Sat, 2 Nov 2024 19:35:12 +0000
Subject: [PATCH 05/18] Improvements
---
README.md | 14 +++++++++-----
website/.vitepress/config.mts | 34 ++++++++++++++++++++--------------
2 files changed, 29 insertions(+), 19 deletions(-)
diff --git a/README.md b/README.md
index 7e6364d9..2fdddbde 100644
--- a/README.md
+++ b/README.md
@@ -161,27 +161,31 @@ The builders generated by `bon`'s macros use the typestate pattern to make sure
If something is wrong, a compile error will be created. No matter how you use the generated builder a panic is never possible.
-| ⭐ Don't forget to give our repo a [star on Github](https://github.com/elastio/bon) ⭐! |
+
+
+| ⭐ Don't forget to give our repo a [star on Github ⭐](https://github.com/elastio/bon)! |
| --- |
+
-
-| Resource | Description
-| -- | -- |
-| [📖 Guide Book](https://bon-rs.com/guide/overview) |Narrative introduction
-| [🔍 API Reference](https://bon-rs.com/reference/builder) | Attributes API index
-
-
-
-## Overview
-
`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.
-If you wonder "Why would I use builders?", see the [motivational blog post](https://bon-rs.com/blog/how-to-do-named-function-arguments-in-rust).
+Visit the [guide for a complete overview of the crate](https://bon-rs.com/guide/overview).
+
+## Quick examples
-## Function Builder
+### Builder for a free function
-You can turn a function with positional parameters into a function with named parameters just by placing `#[builder]` on top of it.
+You can turn a function with positional parameters into a function with named parameters just by placing the `#[builder]` attribute on top of it.
```rust
use bon::builder;
@@ -69,13 +60,9 @@ let greeting = greet()
assert_eq!(greeting, "Hello Bon! Your level is 24");
```
-Any syntax for functions is supported including `async`, fallible, generic functions, `impl Trait`, etc.
+### Builder for an associated method
-## Method Builder
-
-Associated methods require `#[bon]` on top of the impl block.
-
-The method named `new` generates `builder()/build()` methods.
+For associated methods you also need to add the `#[bon]` macro on top of the impl block.
```rust
use bon::bon;
@@ -85,49 +72,41 @@ struct User {
name: String,
}
-#[bon]
+#[bon] // <- this attribute is required on impl blocks that contain `#[builder]`
impl User {
#[builder]
fn new(id: u32, name: String) -> Self {
Self { id, name }
}
-}
-
-let user = User::builder()
- .id(1)
- .name("Bon".to_owned())
- .build();
-
-assert_eq!(user.id, 1);
-assert_eq!(user.name, "Bon");
-```
-
-All other methods generate `{method_name}()/call()` methods.
-```rust
-#[bon]
-impl User {
#[builder]
- fn greet(&self, target: &str, prefix: Option<&str>) -> String {
- let prefix = prefix.unwrap_or("INFO");
+ fn greet(&self, target: &str, level: Option<&str>) -> String {
+ let level = level.unwrap_or("INFO");
let name = &self.name;
- format!("[{prefix}] {name} says hello to {target}")
+ 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")
- // `prefix` is optional, we can omit it here
+ // `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");
```
-Methods with or without `self` are both supported.
-
-## Struct Builder
+### Builder for a struct
The `#[derive(Builder)]` macro generates a builder for a struct.
@@ -154,38 +133,13 @@ assert_eq!(user.level, Some(24));
assert!(user.is_admin);
```
-## No Panics Possible
-
-The builders generated by `bon`'s macros use the typestate pattern to make sure 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.
+See [the guide](https://bon-rs.com/guide/overview) for more.
+---
-
-
-| ⭐ 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 rest of the `Basics` section starting from [the next page](https://bon-rs.com/guide/optional-members) that details on optional/default values handling. Remember, knowledge is power 🐱!
-
-The [🔍 API Reference](https://bon-rs.com/reference/builder) will help you navigate in the attributes once you feel comfortable with the basics of `bon`.
-
-## Installation
-
-Add `bon` to your `Cargo.toml`.
-
-```toml
-[dependencies]
-bon = "2.3"
-```
-
-You can opt out of `std` and `alloc` cargo features with `default-features = false` for `no_std` environments.
+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](https://github.com/elastio/bon). Any support and contribution are appreciated 🐱!
-## License
+#### License
Licensed under either of Apache License, Version
diff --git a/README.v3.md b/README.v3.md
new file mode 100644
index 00000000..2fdddbde
--- /dev/null
+++ b/README.v3.md
@@ -0,0 +1,201 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+| Resource | Description
+| -- | -- |
+| [📖 Guide Book](https://bon-rs.com/guide/overview) |Narrative introduction
+| [🔍 API Reference](https://bon-rs.com/reference/builder) | Attributes API index
+
+
+
+## Overview
+
+`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.
+
+If you wonder "Why would I use builders?", see the [motivational blog post](https://bon-rs.com/blog/how-to-do-named-function-arguments-in-rust).
+
+## Function Builder
+
+You can turn a function with positional parameters into a function with named parameters just by placing `#[builder]` on top of it.
+
+```rust
+use bon::builder;
+
+#[builder]
+fn greet(name: &str, level: Option) -> 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");
+```
+
+Any syntax for functions is supported including `async`, fallible, generic functions, `impl Trait`, etc.
+
+## Method Builder
+
+Associated methods require `#[bon]` on top of the impl block.
+
+The method named `new` generates `builder()/build()` methods.
+
+```rust
+use bon::bon;
+
+struct User {
+ id: u32,
+ name: String,
+}
+
+#[bon]
+impl User {
+ #[builder]
+ fn new(id: u32, name: String) -> Self {
+ Self { id, name }
+ }
+}
+
+let user = User::builder()
+ .id(1)
+ .name("Bon".to_owned())
+ .build();
+
+assert_eq!(user.id, 1);
+assert_eq!(user.name, "Bon");
+```
+
+All other methods generate `{method_name}()/call()` methods.
+
+```rust
+#[bon]
+impl User {
+ #[builder]
+ fn greet(&self, target: &str, prefix: Option<&str>) -> String {
+ let prefix = prefix.unwrap_or("INFO");
+ let name = &self.name;
+
+ format!("[{prefix}] {name} says hello to {target}")
+ }
+}
+
+let greeting = user
+ .greet()
+ .target("the world")
+ // `prefix` is optional, we can omit it here
+ .call();
+
+assert_eq!(greeting, "[INFO] Bon says hello to the world");
+```
+
+Methods with or without `self` are both supported.
+
+## Struct Builder
+
+The `#[derive(Builder)]` macro generates a builder for a struct.
+
+```rust
+use bon::Builder;
+
+#[derive(Builder)]
+struct User {
+ name: String,
+ is_admin: bool,
+ level: Option,
+}
+
+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);
+```
+
+## No Panics Possible
+
+The builders generated by `bon`'s macros use the typestate pattern to make sure 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.
+
+
+
+
+| ⭐ 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 rest of the `Basics` section starting from [the next page](https://bon-rs.com/guide/optional-members) that details on optional/default values handling. Remember, knowledge is power 🐱!
+
+The [🔍 API Reference](https://bon-rs.com/reference/builder) will help you navigate in the attributes once you feel comfortable with the basics of `bon`.
+
+## Installation
+
+Add `bon` to your `Cargo.toml`.
+
+```toml
+[dependencies]
+bon = "2.3"
+```
+
+You can opt out of `std` and `alloc` cargo features with `default-features = false` for `no_std` environments.
+
+## 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.
+
From 380f9178a4fcd7f3192b850549941abb490b098c Mon Sep 17 00:00:00 2001
From: Veetaha
Date: Sat, 2 Nov 2024 20:34:44 +0000
Subject: [PATCH 07/18] Update readme
---
README.md | 161 ++++++++++++++++++++++++-----------
README.v3.md => README.v2.md | 98 ++++++---------------
2 files changed, 138 insertions(+), 121 deletions(-)
rename README.v3.md => README.v2.md (58%)
diff --git a/README.md b/README.md
index 3e3903bd..b00f745c 100644
--- a/README.md
+++ b/README.md
@@ -9,7 +9,7 @@
/>
-
-`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](https://bon-rs.com/guide/overview).
+
-## Quick examples
+# Overview
-### Builder for a free function
+`bon` is a Rust crate for generating compile-time-checked builders for structs and functions. It also provides idiomatic partial application with optional and named parameters for functions and methods.
-You can turn a function with positional parameters into a function with named parameters just by placing the `#[builder]` attribute on top of it.
+If you wonder "Why would I use builders?", see the [motivational blog post](https://bon-rs.com/blog/how-to-do-named-function-arguments-in-rust).
+
+## Function Builder
+
+You can turn a function with positional parameters into a function with named parameters just by placing `#[builder]` on top of it.
```rust
use bon::builder;
@@ -60,9 +75,42 @@ let greeting = greet()
assert_eq!(greeting, "Hello Bon! Your level is 24");
```
-### Builder for an associated method
+Any syntax for functions is supported including `async`, fallible, generic functions, `impl Trait`, etc.
+
+## Struct Builder
+
+Use `#[derive(Builder)]` to generate a builder for a struct.
+
+```rust
+use bon::Builder;
+
+#[derive(Builder)]
+struct User {
+ name: String,
+ is_admin: bool,
+ level: Option,
+}
+
+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);
+```
+
+## Method Builder
+
+Associated methods require `#[bon]` on top of the impl block additionally.
+
+### Method `new`
-For associated methods you also need to add the `#[bon]` macro on top of the impl block.
+The method named `new` generates `builder()/build()` methods.
```rust
use bon::bon;
@@ -72,74 +120,89 @@ struct User {
name: String,
}
-#[bon] // <- this attribute is required on impl blocks that contain `#[builder]`
+#[bon]
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
+### Other Methods
-The `#[derive(Builder)]` macro generates a builder for a struct.
+All other methods generate `{method_name}()/call()` methods.
```rust
-use bon::Builder;
+use bon::bon;
-#[derive(Builder)]
-struct User {
+struct Greeter {
name: String,
- is_admin: bool,
- level: Option,
}
-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();
+#[bon]
+impl Greeter {
+ #[builder]
+ fn greet(&self, target: &str, prefix: Option<&str>) -> String {
+ let prefix = prefix.unwrap_or("INFO");
+ let name = &self.name;
-assert_eq!(user.name, "Bon");
-assert_eq!(user.level, Some(24));
-assert!(user.is_admin);
+ format!("[{prefix}] {name} says hello to {target}")
+ }
+}
+
+let greeter = Greeter { name: "Bon".to_owned() };
+
+let greeting = greeter
+ .greet()
+ .target("the world")
+ // `prefix` is optional, we can omit it here
+ .call();
+
+assert_eq!(greeting, "[INFO] Bon says hello to the world");
```
-See [the guide](https://bon-rs.com/guide/overview) for more.
+Methods with or without `self` are both supported.
+
+## No Panics Possible
+
+Builders generated by `bon`'s macros use the typestate pattern to make sure 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.
----
+
+
+| ⭐ 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 rest of the `Basics` section starting from [the next page](https://bon-rs.com/guide/optional-members) that details on optional/default values handling. Remember, knowledge is power 🐱!
+
+The [🔍 API Reference](https://bon-rs.com/reference/builder) will help you navigate in the attributes once you feel comfortable with the basics of `bon`.
+
+## Installation
+
+Add `bon` to your `Cargo.toml`.
+
+```toml
+[dependencies]
+bon = "2.3"
+```
-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](https://github.com/elastio/bon). Any support and contribution are appreciated 🐱!
+You can opt out of `std` and `alloc` cargo features with `default-features = false` for `no_std` environments.
-#### License
+## License
Licensed under either of Apache License, Version
diff --git a/README.v3.md b/README.v2.md
similarity index 58%
rename from README.v3.md
rename to README.v2.md
index 2fdddbde..3e3903bd 100644
--- a/README.v3.md
+++ b/README.v2.md
@@ -32,24 +32,15 @@
/>
-
-
-| Resource | Description
-| -- | -- |
-| [📖 Guide Book](https://bon-rs.com/guide/overview) |Narrative introduction
-| [🔍 API Reference](https://bon-rs.com/reference/builder) | Attributes API index
-
-
-
-## Overview
-
`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.
-If you wonder "Why would I use builders?", see the [motivational blog post](https://bon-rs.com/blog/how-to-do-named-function-arguments-in-rust).
+Visit the [guide for a complete overview of the crate](https://bon-rs.com/guide/overview).
+
+## Quick examples
-## Function Builder
+### Builder for a free function
-You can turn a function with positional parameters into a function with named parameters just by placing `#[builder]` on top of it.
+You can turn a function with positional parameters into a function with named parameters just by placing the `#[builder]` attribute on top of it.
```rust
use bon::builder;
@@ -69,13 +60,9 @@ let greeting = greet()
assert_eq!(greeting, "Hello Bon! Your level is 24");
```
-Any syntax for functions is supported including `async`, fallible, generic functions, `impl Trait`, etc.
+### Builder for an associated method
-## Method Builder
-
-Associated methods require `#[bon]` on top of the impl block.
-
-The method named `new` generates `builder()/build()` methods.
+For associated methods you also need to add the `#[bon]` macro on top of the impl block.
```rust
use bon::bon;
@@ -85,49 +72,41 @@ struct User {
name: String,
}
-#[bon]
+#[bon] // <- this attribute is required on impl blocks that contain `#[builder]`
impl User {
#[builder]
fn new(id: u32, name: String) -> Self {
Self { id, name }
}
-}
-
-let user = User::builder()
- .id(1)
- .name("Bon".to_owned())
- .build();
-
-assert_eq!(user.id, 1);
-assert_eq!(user.name, "Bon");
-```
-
-All other methods generate `{method_name}()/call()` methods.
-```rust
-#[bon]
-impl User {
#[builder]
- fn greet(&self, target: &str, prefix: Option<&str>) -> String {
- let prefix = prefix.unwrap_or("INFO");
+ fn greet(&self, target: &str, level: Option<&str>) -> String {
+ let level = level.unwrap_or("INFO");
let name = &self.name;
- format!("[{prefix}] {name} says hello to {target}")
+ 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")
- // `prefix` is optional, we can omit it here
+ // `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");
```
-Methods with or without `self` are both supported.
-
-## Struct Builder
+### Builder for a struct
The `#[derive(Builder)]` macro generates a builder for a struct.
@@ -154,38 +133,13 @@ assert_eq!(user.level, Some(24));
assert!(user.is_admin);
```
-## No Panics Possible
-
-The builders generated by `bon`'s macros use the typestate pattern to make sure 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.
+See [the guide](https://bon-rs.com/guide/overview) for more.
+---
-
-
-| ⭐ Don't forget to give our repo a [star on Github ⭐](https://github.com/elastio/bon)! |
-| --- |
-
-
From bae3f02ff6798aa961575a3fe953e9691c266d57 Mon Sep 17 00:00:00 2001
From: Veetaha
Date: Sat, 2 Nov 2024 20:40:07 +0000
Subject: [PATCH 10/18] Improvements
---
README.md | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/README.md b/README.md
index 5cde95e8..b1147272 100644
--- a/README.md
+++ b/README.md
@@ -54,11 +54,11 @@
`bon` is a Rust crate for generating compile-time-checked builders for structs and functions. It also provides idiomatic partial application with optional and named parameters for functions and methods.
-If you wonder "Why would I use builders?", see the [motivational blog post](https://bon-rs.com/blog/how-to-do-named-function-arguments-in-rust).
+If you wonder "Why would I use builders?" then see the [motivational blog post](https://bon-rs.com/blog/how-to-do-named-function-arguments-in-rust).
## Function Builder
-You can turn a function with positional parameters into a function with named parameters just by placing `#[builder]` on top of it.
+You can turn a function with positional parameters into a function with named parameters with `#[builder]`.
```rust
use bon::builder;
@@ -177,7 +177,7 @@ Methods with or without `self` are both supported.
## No Panics Possible
-Builders generated by `bon`'s macros use the typestate pattern to make sure all required parameters are filled, and the same setters aren't called repeatedly to prevent unintentional overwrites.
+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.
@@ -190,7 +190,7 @@ If something is wrong, a compile error will be created. No matter how you use th
## 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 rest of the `Basics` section starting from [the next page](https://bon-rs.com/guide/optional-members) that details on optional/default values handling. Remember, knowledge is power 🐱!
+What you've seen above is the first page of the 📖 [Guide Book](https://bon-rs.com/guide/overview). Consider reading the rest of the `Basics` section starting from [the next page](https://bon-rs.com/guide/optional-members) that describes optional/default values handling. Remember, knowledge is power 🐱!
The [🔍 API Reference](https://bon-rs.com/reference/builder) will help you navigate in the attributes once you feel comfortable with the basics of `bon`.
From 9e25e0b012e4a542dbde2bf1eddced1adca9c119 Mon Sep 17 00:00:00 2001
From: Veetaha
Date: Sat, 2 Nov 2024 20:41:55 +0000
Subject: [PATCH 11/18] Better!
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index b1147272..94ac056f 100644
--- a/README.md
+++ b/README.md
@@ -190,7 +190,7 @@ If something is wrong, a compile error will be created. No matter how you use th
## 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 rest of the `Basics` section starting from [the next page](https://bon-rs.com/guide/optional-members) that describes optional/default values handling. Remember, knowledge is power 🐱!
+What you've seen above is the first page of the 📖 [Guide Book](https://bon-rs.com/guide/overview). Consider reading the rest of the `Basics` section. Here is [the next page](https://bon-rs.com/guide/optional-members) that describes optional/default values handling. Remember, knowledge is power 🐱!
The [🔍 API Reference](https://bon-rs.com/reference/builder) will help you navigate in the attributes once you feel comfortable with the basics of `bon`.
From 4b1195f754eeb4984a15b8f1424a755c48d043d5 Mon Sep 17 00:00:00 2001
From: Veetaha
Date: Sat, 2 Nov 2024 21:38:49 +0000
Subject: [PATCH 12/18] Update readme and overview
---
README.md | 44 ++++++-
website/data/version.data.ts | 11 --
website/src/guide/overview.md | 220 +------------------------------
website/src/v2/guide/overview.md | 10 +-
4 files changed, 44 insertions(+), 241 deletions(-)
delete mode 100644 website/data/version.data.ts
diff --git a/README.md b/README.md
index 94ac056f..5cd82ee8 100644
--- a/README.md
+++ b/README.md
@@ -80,6 +80,8 @@ 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` has to offer.
+
## Struct Builder
Use `#[derive(Builder)]` to generate a builder for a struct.
@@ -140,6 +142,8 @@ 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]` attribute on the `new()` method with a signature similar to the struct's fields (more details on the [compatibility](https://bon-rs.com/guide/compatibility#switching-between-derive-builder-and-builder-on-the-new-method) page).
+
### Other Methods
All other methods generate `{method_name}()/call()` methods.
@@ -167,7 +171,7 @@ let greeter = Greeter { name: "Bon".to_owned() };
let greeting = greeter
.greet()
.target("the world")
- // `prefix` is optional, we can omit it here
+ // `prefix` is optional, omitting it is fine
.call();
assert_eq!(greeting, "[INFO] Bon says hello to the world");
@@ -190,9 +194,11 @@ If something is wrong, a compile error will be created. No matter how you use th
## 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 rest of the `Basics` section. Here is [the next page](https://bon-rs.com/guide/optional-members) that describes optional/default values handling. Remember, knowledge is power 🐱!
+What you've seen above is the first page of the 📖 [Guide Book](https://bon-rs.com/guide/overview). Consider reading the rest of the `Basics` section. You can proceed with [this page](https://bon-rs.com/guide/optional-members), that describes optional/default values handling. 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.
-The [🔍 API Reference](https://bon-rs.com/reference/builder) will help you navigate in the attributes once you feel comfortable with the basics of `bon`.
+The [🔍 API Reference](https://bon-rs.com/reference/builder) will help you navigate in the attributes once you feel comfortable with the basics of `bon`. Both `#[derive(Builder)]` on structs and `#[builder]` on functions/methods have almost the same attributes API, so the documentation for them is common.
## Installation
@@ -205,6 +211,36 @@ bon = "2.3"
You can opt out of `std` and `alloc` cargo features with `default-features = false` for `no_std` environments.
+## Getting Help
+
+If you can't figure something out, consult the docs and maybe use the `🔍 Search` at the top of the page 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) (see below).
+
+## Socials
+
+
+
Profile of the maintainer. There are only posts about bon and Rust in general here.
+
+
+
+
+## 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.
+
## License
@@ -219,3 +255,5 @@ 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.
+
+
diff --git a/website/data/version.data.ts b/website/data/version.data.ts
deleted file mode 100644
index 27afdbdf..00000000
--- a/website/data/version.data.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-import toml from "smol-toml";
-import fs from "node:fs/promises";
-
-export default {
- watch: ['../../bon/Cargo.toml'],
- async load([cargoTomlPath]: [string]) {
- const cargoTomlContent = await fs.readFile(cargoTomlPath, "utf-8");
- const cargoToml = toml.parse(cargoTomlContent) as any;
- return cargoToml.package.version;
- }
-}
diff --git a/website/src/guide/overview.md b/website/src/guide/overview.md
index f6749354..796583ec 100644
--- a/website/src/guide/overview.md
+++ b/website/src/guide/overview.md
@@ -1,219 +1 @@
-
-
-# Overview
-
-`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.
-
-If you are new to the concept of builders or named function arguments, and you don't know what problems they may solve for you, then check out the [motivational blog post](../blog/how-to-do-named-function-arguments-in-rust).
-
-## Installation
-
-Add this to your `Cargo.toml` to use this crate:
-
-```toml-vue
-[dependencies]
-bon = "{{ versionWildcard }}"
-```
-
-You can opt out of `std` and `alloc` cargo features with `default-features = false` for `no_std` environments.
-
-
-## Builder for a function
-
-`bon` can turn a function with positional parameters into a function with "named" parameters via a builder. It's as easy as placing the `#[builder]` macro on top of it.
-
-**Example:**
-
-```rust
-use bon::builder;
-
-#[builder] // [!code highlight]
-fn greet(name: &str, age: u32) -> String {
- format!("Hello {name} with age {age}!")
-}
-
-let greeting = greet()
- .name("Bon")
- .age(24)
- .call();
-
-assert_eq!(greeting, "Hello Bon with age 24!");
-```
-
-::: tip
-
-Many things are customizable with additional attributes. [`#[builder]` macro reference](../reference/builder) describes all of them.
-
-:::
-
-Any syntax for functions is supported including `async`, fallible, generic functions, `impl Trait`, etc. If you find an edge case where `bon` doesn't work, please [create an issue on GitHub](https://github.com/elastio/bon/issues).
-
-## Builder for an associated method
-
-You can also generate a builder for associated methods. For this to work you need to add a `#[bon]` macro on top of the `impl` block additionally.
-
-**Example:**
-
-```rust
-use bon::bon;
-
-struct Counter {
- val: u32,
-}
-
-#[bon] // <- this macro is required on the impl block // [!code highlight]
-impl Counter {
- #[builder] // [!code highlight]
- fn new(initial: Option) -> Self {
- Self {
- val: initial.unwrap_or_default(),
- }
- }
-
- #[builder] // [!code highlight]
- fn increment(&mut self, diff: u32) {
- self.val += diff;
- }
-}
-
-let mut counter = Counter::builder()
- .initial(3)
- .build();
-
-counter
- .increment()
- .diff(3)
- .call();
-
-assert_eq!(counter.val, 6);
-```
-
-::: details Why is that `#[bon]` macro on top of the `impl` block required? 🤔 (feel free to skip)
-
-There are a couple of technical reasons.
-
-First, it's the lack of surrounding context given to a proc macro in Rust. A proc macro sees only the syntax it is placed on top of. For example, the `#[builder]` macro inside of the `impl` block can't see the `impl Counter` part of the impl block above it. However, it needs that information to tell the actual type of `Self`.
-
-Second, the `#[builder]` proc macro generates new items such as the builder struct type definition, which it needs to output **adjacently** to the `impl` block itself. However, proc macros in Rust can only modify the part of the syntax they are placed on and generate new items on the same level of nesting. The `#[builder]` macro inside of the `impl` block can't just break out of it.
-
-:::
-
-::: details Why does it compile without an import of `bon::builder`? 🤔 (feel free to skip)
-
-This is because there is no separate `#[builder]` proc macro running in this case. Only the `#[bon]` macro handles code generation, it's an active attribute, while `#[builder]` is a dumb inert data attribute (see [the Rust Reference](https://doc.rust-lang.org/reference/attributes.html#active-and-inert-attributes) for details about active and inert attributes).
-
-It wouldn't harm if `bon::builder` was imported. It won't shadow the inert `#[builder]` attribute, but the compiler will report that the import of that macro is unused.
-
-:::
-
-
-To follow the usual Rust builder naming conventions `bon` treats the method named `new` inside of the impl block specially. It generates functions with a bit of different names.
-
-If `#[builder]` is placed on the method called `new`, then the generated functions are called:
-
-| Starting function | Finishing function
-|---------------------------|---------------------
-| `builder() -> {T}Builder` | `build(self) -> T`
-
-For any other methods not called `new` and for any free function the naming is a bit different:
-
-| Starting function | Finishing function
-|------------------------------------------------|---------------------
-| `{fn_name}() -> {T?}{PascalCaseFnName}Builder` | `call(self) -> T`
-
-## Builder for a struct
-
-`bon` supports the classic pattern of annotating a struct to generate a builder with the `#[derive(Builder)]` syntax.
-
-**Example:**
-
-```rust
-use bon::Builder;
-
-#[derive(Builder)]
-struct User {
- id: u32,
- name: String,
-}
-
-let user = User::builder()
- .id(1)
- .name("Bon".to_owned())
- .build();
-
-assert_eq!(user.id, 1);
-assert_eq!(user.name, "Bon");
-```
-
-::: tip
-
-`#[derive(Builder)]` on a struct generates builder API that is fully compatible with placing `#[builder]` attribute on the `new()` method with a signature similar to the struct's fields.
-
-See [compatibility](./compatibility#switching-between-derive-builder-and-builder-on-the-new-method) page for details.
-:::
-
-In general, both `#[derive(Builder)]` on structs and `#[builder]` on functions/methods have almost the same API. We'll use both of them throughout the documentation to provide examples. If the example shows only the usage of one syntax (e.g. `#[builder]`), it's very likely that the other syntax (e.g. `#[derive(Builder)]`) works similarly unless explicitly stated otherwise.
-
-## What's next?
-
-::: tip
-
-If you like the idea of this crate and want to say "thank you" or "keep up doing this" consider giving us a [star ⭐ on Github](https://github.com/elastio/bon). Any support and contribution are appreciated 🐱!
-
-:::
-
-This is just part of what's available in `bon`. You may consider reading the `Basics` section to harness the full power of `bon`.
-
-You can also consult the [API reference index](../reference/builder) that describes all available configuration attributes. This guide will cover most of them but not all. Check the short descriptions of available attributes to see if something might be of immediate interest to you.
-
-However, feel free to skip the docs and just use the `#[builder]` and `#[derive(Builder)]` in your code. They are designed to be intuitive, so they'll probably do the thing you want them to do already.
-
-If you can't figure something out, consult the docs and maybe use that search `🔍 Search` thing at the top to navigate. 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) (see below).
-
-Click the "Next page" button at the bottom to proceed with the guide.
-
-## Socials
-
-
Profile of the maintainer. There are only posts about bon and Rust in general here.
-
-
-
-
-
-## 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](./alternatives) for comparison.
+
diff --git a/website/src/v2/guide/overview.md b/website/src/v2/guide/overview.md
index d8699b4e..149afc03 100644
--- a/website/src/v2/guide/overview.md
+++ b/website/src/v2/guide/overview.md
@@ -1,9 +1,3 @@
-
-
# Overview
`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.
@@ -14,9 +8,9 @@ If you are new to the concept of builders or named function arguments, and you d
Add this to your `Cargo.toml` to use this crate:
-```toml-vue
+```toml
[dependencies]
-bon = "{{ versionWildcard }}"
+bon = "2.3"
```
You can opt out of `std` and `alloc` cargo features with `default-features = false` for `no_std` environments.
From adf0ad2e942ba1d306356bcf4434b60c99bffece Mon Sep 17 00:00:00 2001
From: Veetaha
Date: Sat, 2 Nov 2024 21:42:30 +0000
Subject: [PATCH 13/18] Remove centering
---
README.md | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/README.md b/README.md
index 5cd82ee8..c3d94e67 100644
--- a/README.md
+++ b/README.md
@@ -185,20 +185,16 @@ Builders generated by `bon`'s macros use the typestate pattern to ensure all req
If something is wrong, a compile error will be created. No matter how you use the generated builder a panic is never possible.
-
-
| ⭐ Don't forget to give our repo a [star on Github ⭐](https://github.com/elastio/bon)! |
| --- |
-
Profile of the maintainer. There are only posts about bon and Rust in general here.
diff --git a/bon-macros/src/builder/builder_gen/state_mod.rs b/bon-macros/src/builder/builder_gen/state_mod.rs
index 170fbb35..9f2d38fc 100644
--- a/bon-macros/src/builder/builder_gen/state_mod.rs
+++ b/bon-macros/src/builder/builder_gen/state_mod.rs
@@ -233,8 +233,9 @@ impl<'a> StateModGenCtx<'a> {
let docs = format!(
"Marker trait that indicates that all required members are set.\n\n\
- In this state, you can finish the building by calling the method \
- [`{builder_ident}::{finish_fn}()`]",
+ In this state, you can finish building by calling the method \
+ [`{builder_ident}::{finish_fn}()`](super::{builder_ident}::{finish_fn}()).
+ ",
);
quote! {
diff --git a/bon/src/examples/comprehensive.rs b/bon/src/examples/comprehensive.rs
new file mode 100644
index 00000000..77a2a714
--- /dev/null
+++ b/bon/src/examples/comprehensive.rs
@@ -0,0 +1,27 @@
+//! Comprehensive example of the generated builder and its typestate API.
+//!
+//! The preliminary reading of [Builder Extensions](https://bon-rs.com/guide/builder-extensions)
+//! guide is recommended to understand how the pieces in this example fit together.
+//!
+//! This module contains a struct [`Example`] that was annotated with [`#[derive(Builder)]`](crate::Builder).
+//! The config [`#[builder(state_mod(vis = "pub"))]`](https://bon-rs.com/reference/builder/top-level/state_mod) was also applied to make
+//! the generated builder's typestate API public and visible here in the docs.
+//!
+//! The following was generated by the macro:
+//! - [`ExampleBuilder`] - the builder struct itself
+//! - [`example_builder`] - the builder's typestate API module
+
+/// Example struct with the `#[derive(Builder)]` annotation.
+#[derive(crate::Builder)]
+#[builder(crate = crate, state_mod(vis = "pub"))]
+pub struct Example {
+ /// Example required member
+ x1: u32,
+
+ /// Example optional member
+ x2: Option,
+
+ /// Example member with a default value.
+ #[builder(default = 2 + 2)]
+ x3: u32,
+}
diff --git a/bon/src/examples/minimal.rs b/bon/src/examples/minimal.rs
new file mode 100644
index 00000000..7b648813
--- /dev/null
+++ b/bon/src/examples/minimal.rs
@@ -0,0 +1,15 @@
+//! Minimal example of the generated builder and its typestate API.
+//!
+//! This documentation was generated as a showcase for the [Builder Extensions]
+//! guide
+//!
+//! [Builder Extensions]: https://bon-rs.com/guide/builder-extensions#builder-type-signature
+
+/// Example struct with the `#[derive(Builder)]` annotation.
+#[derive(crate::Builder)]
+#[builder(crate = crate, state_mod(vis = "pub"))]
+pub struct Example {
+ /// Example required member
+ x1: u32,
+ x2: u32,
+}
diff --git a/bon/src/examples/mod.rs b/bon/src/examples/mod.rs
new file mode 100644
index 00000000..4192a67c
--- /dev/null
+++ b/bon/src/examples/mod.rs
@@ -0,0 +1,2 @@
+pub mod comprehensive;
+pub mod minimal;
diff --git a/bon/src/lib.rs b/bon/src/lib.rs
index 398a3402..9076d325 100644
--- a/bon/src/lib.rs
+++ b/bon/src/lib.rs
@@ -26,3 +26,7 @@ mod collections;
pub mod __;
mod builder_state;
+
+/// Examples of generated builders' APIs.
+#[cfg(doc)]
+pub mod examples;
diff --git a/website/.vitepress/config.mts b/website/.vitepress/config.mts
index d4f86d97..abe63cdd 100644
--- a/website/.vitepress/config.mts
+++ b/website/.vitepress/config.mts
@@ -164,12 +164,17 @@ export default defineConfig({
],
},
{
- text: "Advanced",
+ text: "Typestate API",
+ link: "/guide/typestate-api",
items: [
{
- text: "Builder Extensions",
- link: "/guide/builder-extensions",
+ text: "Builder's Type Signature",
+ link: "/guide/builders-type-signature",
},
+ {
+ text: "Custom Methods",
+ link: "/guide/custom-methods",
+ }
],
},
{
@@ -315,10 +320,6 @@ export default defineConfig({
},
],
},
- {
- text: "Typestate API",
- link: "/reference/builder/typestate-api",
- },
],
},
{
diff --git a/website/src/guide/advanced/builder-extensions.md b/website/src/guide/advanced/builder-extensions.md
deleted file mode 100644
index 253c9cb7..00000000
--- a/website/src/guide/advanced/builder-extensions.md
+++ /dev/null
@@ -1,4 +0,0 @@
-# Builder Extensions
-
-
-## Custom setters
diff --git a/website/src/guide/basics/custom-conversions.md b/website/src/guide/basics/custom-conversions.md
index f334e811..a621ec45 100644
--- a/website/src/guide/basics/custom-conversions.md
+++ b/website/src/guide/basics/custom-conversions.md
@@ -1 +1,31 @@
# Custom Conversions
+
+[`#[builder(into)]`](../../reference/builder/member/into) is great and it works in many cases. However, what if you need to do a conversion that isn't a simple `Into`? What if you want your setter to accept several parameters? What if your setter should be fallible? The answer to all these questions is the bigger brother [`#[builder(with)]`](../../reference/builder/member/with).
+
+You can pass a custom closure to `#[builder(with)]`. It will be used to define the signature of the setter and perform a conversion.
+
+```rust
+use bon::Builder;
+
+struct Point {
+ x: u32,
+ y: u32,
+}
+
+#[derive(Builder)]
+struct Example {
+ #[builder(with = |x: u32, y: u32| Point { x, y })]
+ point: Point,
+}
+
+let value = Example::builder()
+ .point(2, 3)
+ .build();
+
+assert_eq!(value.point.x, 2);
+assert_eq!(value.point.y, 3);
+```
+
+You can also pass a [fallible closure](../../reference/builder/member/with#fallible-setters) and some [well-known functions](../../reference/builder/member/with#well-known-functions) to `#[builder(with)]`.
+
+If your setter needs more complex logic that isn't expressible with `#[builder(with)]` (e.g. mark the setter `unsafe`, set several members at once), then [builder extensions](../guide/builder-extensions#custom-setters) have you covered.
diff --git a/website/src/guide/basics/documenting.md b/website/src/guide/basics/documenting.md
index aec8207e..bc5df75c 100644
--- a/website/src/guide/basics/documenting.md
+++ b/website/src/guide/basics/documenting.md
@@ -33,6 +33,37 @@ This works because Rust compiler checks for invalid placement of `#[doc = ...]`
When `#[derive(Builder)]` is placed on top of a struct, then documentation on the struct fields will be copied to the docs on the setter methods.
+## Custom `doc` attributes
+
+You can override documentation on other items generated by builder macros. There are multiple attributes accepting a `doc { ... }` block.
+
+```rust
+use bon::Builder;
+
+#[derive(Builder)]
+#[builder(
+ builder_type(doc {
+ /// Custom docs on the builder struct itself
+ }),
+ start_fn(doc {
+ /// Custom docs on the starting function
+ }),
+)]
+struct Example {}
+```
+
+You can document the following items this way:
+
+| Attribute | Documentation target
+|------------------------------------------------------------------------|----------------------
+| [`builder_type`](../../reference/builder/top-level/builder_type#doc) | Builder struct
+| [`start_fn`](../../reference/builder/top-level/start_fn#doc) | Starting function
+| [`finish_fn`](../../reference/builder/top-level/finish_fn#doc) | Finishing function
+| [`state_mod`](../../reference/builder/top-level/state_mod#doc) | Builder state API module (more details in [Builder Extensions](../advanced/builder-extensions))
+| [`setters`](../../reference/builder/member/setters#doc) | Custom docs for setters. Prevents copying them from the field/argument
+
+
+
## Positional members
Documentation comments are allowed on [positional members](./positional-members). However, since there are no separate setter methods generated for them, the docs on these members will not be copied anywhere, and thus they won't appear in `rustdoc`. Instead, it's recommended to write documentation for these members on the top level of the struct or function.
diff --git a/website/src/guide/basics/into-conversions.md b/website/src/guide/basics/into-conversions.md
index 057f8a8e..a57b6a26 100644
--- a/website/src/guide/basics/into-conversions.md
+++ b/website/src/guide/basics/into-conversions.md
@@ -41,11 +41,9 @@ struct Project {
}
Project::builder()
- // &str is converted to `String` internally // [!code highlight]
- .name("Bon")
- .description("Awesome crate 🐱")
- // `&str` is converted to `PathBuf` internally // [!code highlight]
- .path("/path/to/your/heart")
+ .name("Bon") // [!code highlight]
+ .description("Awesome crate 🐱") // [!code highlight]
+ .path("/path/to/your/heart") // [!code highlight]
.build();
```
diff --git a/website/src/guide/basics/positional-members.md b/website/src/guide/basics/positional-members.md
index 18847842..8910aa7a 100644
--- a/website/src/guide/basics/positional-members.md
+++ b/website/src/guide/basics/positional-members.md
@@ -1,21 +1,10 @@
# Positional Members
-While having the ability to use separate setters for the members gives you a ton of flexibility and extensibility described on the ["Compatibility"](./compatibility) page, sometimes you don't need all of that.
-
-Maybe you'd like to pick out some specific members and let the user pass their values as positional parameters to the starting function that creates the builder or to the finishing function that consumes it. This reduces the syntax a bit at the cost of some extensibility loss ⚖️, but it may be worth it!
+You can let the caller pass some values as positional parameters to the starting function that creates the builder or to the finishing function that consumes it.
## Starting function
-As an example, suppose we have a `Treasure` struct with `x` and `y` coordinates and a `label` that describes the payload of the treasure. Since all treasures are located somewhere, they all have coordinates, and it would be cool to specify them in a single starting function call.
-
-To do that we can use the `#[builder(start_fn)]` attribute. There are two contexts where we can place it, and they both have a different meaning:
-
-- [Top-level `#[builder(start_fn = ...)]`](../reference/builder/top-level/start-fn) - configures name, visibility and docs of the starting function
-- [Member-level `#[builder(start_fn)]`](../reference/builder/member/start-fn) - configures the member to be a positional parameter on the starting function
-
-We'll want to use both of these attributes in our example to give a better name for the starting function that describes its inputs and configure `x` and `y` as positional parameters on the starting function as well.
-
-**Example:**
+Use `#[builder(start_fn)]` to move some members to the parameters of the starting function.
```rust
use bon::Builder;
@@ -24,9 +13,9 @@ use bon::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 attributes to make members as // [!code highlight]
- // parameters of `with_coordinates()` // [!code highlight]
- #[builder(start_fn)] // [!code highlight]
+ // Member-level attributes to move members // [!code highlight]
+ // to the parameters of `with_coordinates()` // [!code highlight]
+ #[builder(start_fn)] // [!code highlight]
x: u32,
#[builder(start_fn)] // [!code highlight]
@@ -44,103 +33,47 @@ assert_eq!(treasure.y, 9);
assert_eq!(treasure.label.as_deref(), Some("oats"));
```
-Here, the generated `with_coordinates` method has the following signature:
-
-```rust ignore
-impl Treasure {
- fn with_coordinates(x: u32, y: u32) -> TreasureBuilder { /**/ }
-}
-```
+::: tip
-## Finishing function
+There are two versions of the `#[builder(start_fn)]` used here: [top-level](../../reference/builder/top-level/start_fn) and [member-level](../../reference/builder/member/start_fn).
+They have different meanings.
-Now let's say we need to know the person who claimed the `Treasure`. While describing the treasure using the current builder syntax we'd like the person who claimed it to specify their first name and last name at the end of the building process.
+:::
-We can use a similar combination of the [top-level `#[builder(finish_fn = ...)]`](../reference/builder/top-level/finish-fn) and the [member-level `#[builder(finish_fn)]`](../reference/builder/member/finish-fn) attributes to do that.
+## Finishing function
-**Example:**
+Use `#[builder(finish_fn)]` to move some members to the parameters of the starting function.
```rust
use bon::Builder;
#[derive(Builder)]
-#[builder(
- start_fn = with_coordinates,
- finish_fn = claim // [!code highlight]
-)]
+// Top-level attribute to give a better name for the finishing function // [!code highlight]
+#[builder(finish_fn = located_at)] // [!code highlight]
struct Treasure {
- #[builder(start_fn)]
+ // Member-level attributes to move members // [!code highlight]
+ // to the parameters of `located_at()` // [!code highlight]
+ #[builder(finish_fn)] // [!code highlight]
x: u32,
- #[builder(start_fn)]
+ #[builder(finish_fn)] // [!code highlight]
y: u32,
- #[builder(finish_fn)] // [!code highlight]
- claimed_by_first_name: String, // [!code highlight]
-
- #[builder(finish_fn)] // [!code highlight]
- claimed_by_last_name: String, // [!code highlight]
-
label: Option,
}
-let treasure = Treasure::with_coordinates(2, 9)
+let treasure = Treasure::builder()
.label("oats".to_owned())
- .claim("Lyra".to_owned(), "Heartstrings".to_owned()); // [!code highlight]
+ .located_at(2, 9); // [!code highlight]
assert_eq!(treasure.x, 2);
assert_eq!(treasure.y, 9);
assert_eq!(treasure.label.as_deref(), Some("oats"));
-assert_eq!(treasure.claimed_by_first_name, "Lyra"); // [!code highlight]
-assert_eq!(treasure.claimed_by_last_name, "Heartstrings"); // [!code highlight]
```
-## Into conversions
-
-You may also combine these attributes with [`#[builder(into)]`](../reference/builder/member/into) or [`#[builder(on(..., into))]`](../reference/builder/top-level/on) to reduce the number of `to_owned()` calls a bit.
-
-```rust
-use bon::Builder;
-
-#[derive(Builder)]
-#[builder(
- start_fn = with_coordinates,
- finish_fn = claim // [!code focus]
-)]
-struct Treasure {
- #[builder(start_fn)]
- x: u32,
-
- #[builder(start_fn)]
- y: u32,
-
- #[builder(finish_fn, into)] // [!code focus]
- claimed_by_first_name: String, // [!code focus]
-
- #[builder(finish_fn, into)] // [!code focus]
- claimed_by_last_name: String, // [!code focus]
-
- #[builder(into)] // [!code focus]
- label: Option, // [!code focus]
-}
-
-let treasure = Treasure::with_coordinates(2, 9)
- .label("oats") // [!code focus]
- .claim("Lyra", "Heartstrings"); // [!code focus]
-```
-
-However, keep in mind that positional members (ones annotated with `#[builder(start_fn/finish_fn)]`) are always required to pass. There is no special treatment of the `Option` type for such members.
-
-For example `#[builder(into)]` on a regular (named) member of the `Option` type generates two setters:
-- One that accepts `impl Into`.
-- The other that accepts `Option>`.
-
-For positional members, the story is completely different because there are no separate setters generated for them. There is just a single starting or finishing function. So if you enable an into conversion for a positional member of the `Option` type, it will be accepted as `impl Into
>` in the starting or finishing function.
-
-Also, the type pattern of the `#[builder(on(..., into))]` attribute matches the `Option` fully. So, for example `on(String, into)` will not match the positional member of type `Option`, but `on(Option, into)` will.
-
::: tip
-In general, it's not recommended to annotate optional members with `#[builder(start_fn/finish_fn)]` because you can't omit setting them using the positional function call syntax.
+There are two versions of the `#[builder(finish_fn)]` used here: [top-level](../../reference/builder/top-level/finish_fn) and [member-level](../../reference/builder/member/finish_fn).
+They have different meanings.
:::
diff --git a/website/src/guide/typestate-api/builders-type-signature.md b/website/src/guide/typestate-api/builders-type-signature.md
new file mode 100644
index 00000000..2aec904f
--- /dev/null
+++ b/website/src/guide/typestate-api/builders-type-signature.md
@@ -0,0 +1,111 @@
+# Builder's Type Signature
+
+On this page, you'll learn how to spell the exact builder's type 📝.
+
+## Builder's Type Name
+
+The builder's type name is derived from the underlying item from which it was generated by default.
+
+
+
+It can also be overridden with [`#[builder(builder_type = NewName)]`](../../reference/builder/top-level/builder_type).
+
+## Generic Typestate Parameter
+
+Builders generated by `bon` macros use the typestate pattern. Every time you call a setter the builder's type changes. The builder's typestate doesn't depend on the syntax from which it was generated (struct or function).
+
+The builder always contains a generic parameter `S` (stands for "state") at the end. This parameter holds the type state that describes what members were set in the builder.
+
+It's probably easier to understand with an example. Don't worry, the next paragraph will explain it.
+
+```rust
+use bon::Builder;
+
+#[derive(Builder)]
+struct Example {
+ x1: u32,
+ x2: u32,
+}
+
+// Import type states from the generated module
+use example_builder::{SetX1, SetX2};
+
+let builder: ExampleBuilder = Example::builder();
+let builder: ExampleBuilder = builder.x1(1);
+let builder: ExampleBuilder> = builder.x2(2);
+```
+
+Notice the pattern here. Every time we set a member, we wrap the previous type state with a new `Set{Member}` type state transition.
+
+There is a special `Empty` type state, which is used as the default value for the generic parameter `S` in two places:
+- The builder type itself: `ExampleBuilder`
+- The type state transitions: `Set{Member}`
+
+The type states come from the builder's state module. The name of that module is the `snake_case` version of the builder's name.
+
+## Visibility
+
+The type state module is private by default, and only accessible within the module where the builder macro was used. This way the builder type becomes unnameable outside of the module where it was generated.
+
+If you want to expose your builder's type signature, you need to add [`#[builder(state_mod(vis = "..."))]`](../../reference/builder/top-level/state_mod), where `...` can be `pub` or `pub(crate)` or any other visibility you want to expose the state module under.
+
+## Example Rustdoc
+
+You can see the `rustdoc` API reference generated for this example [here](https://docs.rs/bon/latest/bon/examples/minimal/). Note that it was generated with `#[builder(state_mod(vis = "pub"))]`, otherwise, it wouldn't appear in public documentation.
+
+## Other Generic Parameters
+
+The builder inherits all generic parameters from the struct or function from which it was generated.
+
+Functions may even use anonymous lifetimes and `impl Trait` syntax. Every such anonymous lifetime or `impl Trait` will get a separate generic parameter generated in the builder's type automatically.
+
+::: code-group
+
+```rust [Struct]
+use bon::Builder;
+
+#[derive(Builder)]
+struct Example<'a, T> {
+ x1: &'a T,
+}
+
+let builder: ExampleBuilder<'_, bool, _> = Example::builder().x1(&true);
+ // ^- type state (always last)
+```
+
+```rust [Function]
+use bon::builder;
+
+#[builder]
+fn example(
+ x1: &impl Clone
+) {}
+
+let builder: ExampleBuilder<'_, bool, _> = example().x1(&true);
+ // ^- type state (always last)
+```
+
+```rust [Method]
+use bon::bon;
+
+struct Example;
+
+#[bon]
+impl Example {
+ #[builder]
+ fn method(x1: &impl Clone) {}
+}
+
+let builder: ExampleMethodBuilder<'_, bool, _> = Example::method().x1(&true);
+ // ^- type state (always last)
+```
+
+:::
+
+If there is a mix of named and anonymous lifetimes or named generic types and `impl Trait`, then the generated generic lifetimes and types will be appended at the end of the list of named lifetimes and other named generic parameters respectively.
+
+## What's Next?
+
+Now you know the mechanics of how a builder's type is built, so you can denote it when it's returned from a function or stored in a struct.
+
+However, to be able to write useful custom methods on the builder, you'll need to know the `trait`s behind the type states. Go to the next page to learn more.
diff --git a/website/src/guide/typestate-api/custom-methods.md b/website/src/guide/typestate-api/custom-methods.md
new file mode 100644
index 00000000..f978829f
--- /dev/null
+++ b/website/src/guide/typestate-api/custom-methods.md
@@ -0,0 +1,4 @@
+# Custom Methods
+
+
+- add custom methods to the builder type 💪
diff --git a/website/src/guide/typestate-api/typestate-api.md b/website/src/guide/typestate-api/typestate-api.md
new file mode 100644
index 00000000..dce76a7e
--- /dev/null
+++ b/website/src/guide/typestate-api/typestate-api.md
@@ -0,0 +1,7 @@
+# Typestate API
+
+This section will teach you the builder's typestate API. It'll describe the underlying component traits and types of the builder type and how to use them.
+
+Reading this is optional. The typestate API is private by default. The users of your builder can't denote its type unless you enable [`#[builder(state_mod(vis = "pub"))]`](../../reference/builder/top-level/state_mod).
+
+It is more of an advanced concept that you'll rarely need. However, "advanced" doesn't necessarily mean "complicated" in this case. So feel free to study this section if you feel like it.
diff --git a/website/src/reference/builder.md b/website/src/reference/builder.md
index 3acc2e95..c0627d02 100644
--- a/website/src/reference/builder.md
+++ b/website/src/reference/builder.md
@@ -51,7 +51,7 @@ struct Example {
}
```
-```rust [Free function]
+```rust [Function]
use bon::builder;
#[builder(finish_fn = finish)] // <-- this is a top-level attribute // [!code highlight]
@@ -61,7 +61,7 @@ fn example(
) { }
```
-```rust [Associated method]
+```rust [Method]
use bon::bon;
struct Example;
diff --git a/website/src/reference/builder/member/default.md b/website/src/reference/builder/member/default.md
index 53f2800c..0810fc17 100644
--- a/website/src/reference/builder/member/default.md
+++ b/website/src/reference/builder/member/default.md
@@ -66,7 +66,7 @@ assert_eq!(value.bar, "anon");
assert_eq!(value.baz, "lyra");
```
-```rust [Free function]
+```rust [Function]
use bon::builder;
#[builder]
@@ -101,7 +101,7 @@ assert_eq!(value.1, "anon");
assert_eq!(value.2, "lyra");
```
-```rust [Associated method]
+```rust [Method]
use bon::bon;
struct Example {
@@ -178,7 +178,7 @@ assert_eq!(value.bar, 6);
assert_eq!(value.baz, 9);
```
-```rust [Free function]
+```rust [Function]
use bon::builder;
#[builder]
@@ -203,7 +203,7 @@ let value = example()
assert_eq!(value, (3, 6, 9));
```
-```rust [Associated method]
+```rust [Method]
use bon::bon;
struct Example;
diff --git a/website/src/reference/builder/member/finish_fn.md b/website/src/reference/builder/member/finish_fn.md
index dd626374..58b650fe 100644
--- a/website/src/reference/builder/member/finish_fn.md
+++ b/website/src/reference/builder/member/finish_fn.md
@@ -2,13 +2,11 @@
**Applies to:**
-Makes the member a positional argument on the finishing function that consumes the builder and returns the resulting object (for struct syntax) or performs the requested action (for function/method syntax).
+Makes the member a positional argument on the finishing function.
::: tip
-Don't confuse this with the top-level [`#[builder(finish_fn = ...)]`](../top-level/finish-fn) attribute.
-
-See ["Positional Members"](../../../guide/positional-members#finishing-function) guide page for details.
+Don't confuse this with the [top-level](../top-level/finish_fn) `#[builder(finish_fn)]` attribute.
:::
@@ -37,7 +35,7 @@ assert_eq!(value.bar, 2);
assert_eq!(value.baz, 3);
```
-```rust [Free function]
+```rust [Function]
use bon::builder;
#[builder]
@@ -62,7 +60,7 @@ assert_eq!(value.1, 2);
assert_eq!(value.2, 3);
```
-```rust [Associated method]
+```rust [Method]
use bon::bon;
struct Example;
diff --git a/website/src/reference/builder/member/into.md b/website/src/reference/builder/member/into.md
index b99a2c45..872149a5 100644
--- a/website/src/reference/builder/member/into.md
+++ b/website/src/reference/builder/member/into.md
@@ -48,7 +48,7 @@ Example::builder()
.build();
```
-```rust [Free function]
+```rust [Function]
use bon::builder;
#[builder]
@@ -74,7 +74,7 @@ example()
.call();
```
-```rust [Associated method]
+```rust [Method]
use bon::bon;
struct Example;
diff --git a/website/src/reference/builder/member/name.md b/website/src/reference/builder/member/name.md
index 0dadf29d..7ba10482 100644
--- a/website/src/reference/builder/member/name.md
+++ b/website/src/reference/builder/member/name.md
@@ -22,7 +22,7 @@ Player::builder()
.build();
```
-```rust [Free function]
+```rust [Function]
use bon::builder;
#[builder]
@@ -36,7 +36,7 @@ player()
.call();
```
-```rust [Associated method]
+```rust [Method]
use bon::bon;
struct Player {
diff --git a/website/src/reference/builder/member/setters.md b/website/src/reference/builder/member/setters.md
index c07c8a0b..185a3dff 100644
--- a/website/src/reference/builder/member/setters.md
+++ b/website/src/reference/builder/member/setters.md
@@ -71,7 +71,7 @@ The default name for setters is chosen according to the following rules:
| Required | `{member}`
| Optional | `some_fn` = `{member}` `option_fn` = `maybe_{member}`
-This attribute is different from [`#[builder(name)]`](./name), because it overrides only the names of setters. It doesn't influence the name of the member in the builder's [typestate API](../typestate-api). This attribute also has higher precedence than [`#[builder(name)]`](./name).
+This attribute is different from [`#[builder(name)]`](./name), because it overrides only the names of setters. It doesn't influence the name of the member in the builder's [typestate API](../../../guide/advanced/builder-extensions). This attribute also has higher precedence than [`#[builder(name)]`](./name).
## `vis`
diff --git a/website/src/reference/builder/member/start_fn.md b/website/src/reference/builder/member/start_fn.md
index 610bf4ad..02c67e15 100644
--- a/website/src/reference/builder/member/start_fn.md
+++ b/website/src/reference/builder/member/start_fn.md
@@ -6,9 +6,7 @@ Makes the member a positional argument on the starting function that creates the
::: tip
-Don't confuse this with the top-level [`#[builder(start_fn = ...)]`](../top-level/start-fn) attribute.
-
-See ["Positional Members"](../../../guide/positional-members#starting-function) guide page for details.
+Don't confuse this with the [top-level](../top-level/start_fn) `#[builder(start_fn)]` attribute.
:::
@@ -37,7 +35,7 @@ assert_eq!(value.bar, 2);
assert_eq!(value.baz, 3);
```
-```rust [Free function]
+```rust [Function]
use bon::builder;
#[builder]
@@ -62,7 +60,7 @@ assert_eq!(value.1, 2);
assert_eq!(value.2, 3);
```
-```rust [Associated method]
+```rust [Method]
use bon::bon;
struct Example;
diff --git a/website/src/reference/builder/member/with.md b/website/src/reference/builder/member/with.md
index 923d962b..602d3ca5 100644
--- a/website/src/reference/builder/member/with.md
+++ b/website/src/reference/builder/member/with.md
@@ -4,4 +4,45 @@
TODO: add docs (update the short descriptions on the parent page)
+
+If the closure accepts a single parameter `T`, then the `maybe_` setter accepts `Option`. Tuple is unnecessary in this case.
+
+You can use `impl Trait` for parameters in the closure, even though you can't in the usual Rust code.
+
+There are several well-known functions that you can use instead of the closure syntax to shorten your code e.g. `#[builder(with = Some)]` and `#[builder(with = FromIterator::from_iter)]` (more details [here](../../reference/builder/member/with#well-known-functions)).
+
+## Optional members
+
+
+
+
## Well-Known Functions
+
+
+## Fallible setters
+
+You can add a return type annotation to the closure to signify that it's fallible. In this case a fallible setter will be generated.
+
+```rust
+use bon::Builder;
+use std::num::ParseIntError;
+
+#[derive(Builder)]
+struct Example {
+ #[builder(with = |string: &str| -> Result<_, ParseIntError> { // [!code focus]
+ string.parse() // [!code focus]
+ })] // [!code focus]
+ x1: u32, // [!code focus]
+}
+
+fn main() -> Result<(), ParseIntError> {
+ Example::builder()
+ .x1("99")? // <-- the setter returns a `Result` // [!code focus]
+ .build();
+
+ Ok(())
+}
+```
diff --git a/website/src/reference/builder/top-level/builder_type.md b/website/src/reference/builder/top-level/builder_type.md
index b947257c..71afe9d8 100644
--- a/website/src/reference/builder/top-level/builder_type.md
+++ b/website/src/reference/builder/top-level/builder_type.md
@@ -32,6 +32,8 @@ Overrides name, visibility and docs for the builder struct.
The default name for the builder struct is chosen according to the following rules:
+
+
| Syntax | Default
| -----------------------------------|------------------------
| `struct T` | `{T}Builder`
@@ -39,6 +41,8 @@ The default name for the builder struct is chosen according to the following rul
| Associated `fn` `T::fn_name()` | `{T}{FnName}Builder`
| Free `fn` `fn_name()` | `{FnName}Builder`
+
+
## `vis`
The visibility must be enclosed with quotes. Use `""` or [`"pub(self)"`](https://doc.rust-lang.org/reference/visibility-and-privacy.html#pubin-path-pubcrate-pubsuper-and-pubself) for private visibility.
@@ -63,7 +67,7 @@ struct Brush {}
let builder: MyBuilder = Brush::builder();
```
-```rust [Free function]
+```rust [Function]
use bon::builder;
#[builder(builder_type = MyBuilder)] // [!code highlight]
@@ -72,7 +76,7 @@ fn brush() {}
let builder: MyBuilder = brush();
```
-```rust [Associated method]
+```rust [Method]
use bon::bon;
struct Brush;
diff --git a/website/src/reference/builder/top-level/crate.md b/website/src/reference/builder/top-level/crate.md
index c15e9283..2fba89ed 100644
--- a/website/src/reference/builder/top-level/crate.md
+++ b/website/src/reference/builder/top-level/crate.md
@@ -20,12 +20,12 @@ Overrides path to `bon` crate referenced in the generated code, which is useful
struct Example {}
```
-```rust ignore [Free function]
+```rust ignore [Function]
#[::path::to::bon::builder(crate = ::path::to::bon)]
fn example() {}
```
-```rust ignore [Associated method]
+```rust ignore [Method]
struct Example;
#[::path::to::bon::bon(crate = ::path::to::bon)]
diff --git a/website/src/reference/builder/top-level/derive.md b/website/src/reference/builder/top-level/derive.md
index 7bfe2af3..aa2e5014 100644
--- a/website/src/reference/builder/top-level/derive.md
+++ b/website/src/reference/builder/top-level/derive.md
@@ -45,7 +45,7 @@ assert_eq!(
let example = builder.is_admin(true).build();
```
-```rust [Free function]
+```rust [Function]
use bon::builder;
#[builder(derive(Clone, Debug))] // [!code highlight]
@@ -73,7 +73,7 @@ assert_eq!(
builder.is_admin(true).call();
```
-```rust [Associated method]
+```rust [Method]
use bon::bon;
#[derive(Debug)]
diff --git a/website/src/reference/builder/top-level/finish_fn.md b/website/src/reference/builder/top-level/finish_fn.md
index 0163f04b..1e3ee77c 100644
--- a/website/src/reference/builder/top-level/finish_fn.md
+++ b/website/src/reference/builder/top-level/finish_fn.md
@@ -2,7 +2,13 @@
**Applies to:**
-Overrides name, visibility and docs for the builder's method that finishes the building process, i.e. returns the resulting object (in case of `#[derive(Builder)]` on a `struct`) or invokes the underlying function (in case of `#[builder]` on an `fn`). It is commonly referred to as the "finishing function".
+Overrides name, visibility and docs for the finishing function.
+
+::: tip
+
+Don't confuse this with the [member-level](../member/finish_fn) `#[builder(finish_fn)]` attribute.
+
+:::
**Short syntax** configures just the *name*.
@@ -65,7 +71,7 @@ let article = Article::builder()
assert_eq!(article.id, 42);
```
-```rust [Free function]
+```rust [Function]
use bon::builder;
#[builder(finish_fn = send)] // [!code highlight]
@@ -80,7 +86,7 @@ let response = get_article()
assert_eq!(response, "Some article with id 42");
```
-```rust [Associated method]
+```rust [Method]
use bon::bon;
struct ArticlesClient;
diff --git a/website/src/reference/builder/top-level/on.md b/website/src/reference/builder/top-level/on.md
index 69705709..165baeef 100644
--- a/website/src/reference/builder/top-level/on.md
+++ b/website/src/reference/builder/top-level/on.md
@@ -32,7 +32,7 @@ Example::builder()
.build();
```
-```rust [Free function]
+```rust [Function]
use bon::builder;
#[builder(on(String, into))]
@@ -53,7 +53,7 @@ example()
.call();
```
-```rust [Associated method]
+```rust [Method]
use bon::bon;
struct Example;
diff --git a/website/src/reference/builder/top-level/start_fn.md b/website/src/reference/builder/top-level/start_fn.md
index 19e5234a..ca105b4c 100644
--- a/website/src/reference/builder/top-level/start_fn.md
+++ b/website/src/reference/builder/top-level/start_fn.md
@@ -2,7 +2,13 @@
**Applies to:**
-Overrides name, visibility and docs for the function that starts the building process, i.e. returns the builder for the `struct` or `fn`. It is commonly referred to as the "starting function".
+Overrides name, visibility and docs for the starting function.
+
+::: tip
+
+Don't confuse this with the [member-level](../member/start_fn) `#[builder(start_fn)]` attribute.
+
+:::
When this attribute is used with `fn` syntax, it additionally [exposes the original function](#exposing-original-function) under the macro.
@@ -108,7 +114,7 @@ The [`name`](#name) parameter is **required** when `start_fn` is used with `fn`
::: code-group
-```rust [Free function]
+```rust [Function]
use bon::builder;
#[builder(start_fn = example_builder)] // [!code ++]
@@ -124,7 +130,7 @@ example_builder()
.call();
```
-```rust [Associated method]
+```rust [Method]
use bon::bon;
struct Example;
diff --git a/website/src/reference/builder/typestate-api.md b/website/src/reference/builder/typestate-api.md
deleted file mode 100644
index fcc5bbea..00000000
--- a/website/src/reference/builder/typestate-api.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# Typestate API
-
-Preliminary reading of ["Builder Extensions"](../../guide/builder-extensions) guide is recommended to understand how the pieces on this page fit together.
-
-TODO: add docs
From 5ce1bd838a1f556d4aaf1c8b802d6b59ee149828 Mon Sep 17 00:00:00 2001
From: Veetaha
Date: Sun, 3 Nov 2024 04:36:27 +0000
Subject: [PATCH 16/18] Smallfix
---
README.md | 2 +-
website/src/guide/basics/custom-conversions.md | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index 30d81ea3..ed406897 100644
--- a/README.md
+++ b/README.md
@@ -50,7 +50,7 @@
`bon` is a Rust crate for generating compile-time-checked builders for structs and functions. It also provides idiomatic partial application with optional and named parameters for functions and methods.
-If you wonder "Why would I use builders?" then see the [motivational blog post](https://bon-rs.com/blog/how-to-do-named-function-arguments-in-rust).
+If you wonder "Why would I use builders?", see the [motivational blog post](https://bon-rs.com/blog/how-to-do-named-function-arguments-in-rust).
## Function Builder
diff --git a/website/src/guide/basics/custom-conversions.md b/website/src/guide/basics/custom-conversions.md
index a621ec45..2ff41146 100644
--- a/website/src/guide/basics/custom-conversions.md
+++ b/website/src/guide/basics/custom-conversions.md
@@ -28,4 +28,4 @@ assert_eq!(value.point.y, 3);
You can also pass a [fallible closure](../../reference/builder/member/with#fallible-setters) and some [well-known functions](../../reference/builder/member/with#well-known-functions) to `#[builder(with)]`.
-If your setter needs more complex logic that isn't expressible with `#[builder(with)]` (e.g. mark the setter `unsafe`, set several members at once), then [builder extensions](../guide/builder-extensions#custom-setters) have you covered.
+If your setter needs more complex logic that isn't expressible with `#[builder(with)]` (e.g. mark the setter `unsafe`, set several members at once), then [Custom Methods](./custom-methods) can cover that.
From a6765a6c84403d89fbac780943f19e80754cd85f Mon Sep 17 00:00:00 2001
From: Veetaha
Date: Sun, 3 Nov 2024 16:20:26 +0000
Subject: [PATCH 17/18] Self-review
---
README.md | 196 ++++----------
README.v2.md | 155 -----------
README.v3.md | 247 ++++++++++++++++++
.../src/builder/builder_gen/state_mod.rs | 3 +-
bon/src/__/ide.rs | 54 ++--
bon/src/examples/comprehensive.rs | 6 +-
bon/src/examples/minimal.rs | 5 +-
website/.vitepress/config.mts | 42 ++-
website/package-lock.json | 21 +-
website/package.json | 3 +-
.../src/guide/basics/custom-conversions.md | 2 +-
website/src/guide/basics/documenting.md | 5 +-
website/src/guide/basics/into-conversions.md | 2 +-
website/src/guide/basics/optional-members.md | 6 +-
.../src/guide/basics/positional-members.md | 4 +-
.../guide/patterns/conditional-building.md | 6 +-
.../guide/patterns/shared-configuration.md | 4 +-
.../{typestate-api => }/typestate-api.md | 2 +-
.../typestate-api/builders-type-signature.md | 8 +-
.../src/guide/typestate-api/custom-methods.md | 2 +-
.../src/reference/builder/member/default.md | 124 ++++-----
.../src/reference/builder/member/finish_fn.md | 40 +--
website/src/reference/builder/member/into.md | 2 +-
website/src/reference/builder/member/name.md | 2 +-
.../reference/builder/member/overwritable.md | 2 +-
.../src/reference/builder/member/setters.md | 4 +-
website/src/reference/builder/member/skip.md | 2 +-
.../src/reference/builder/member/start_fn.md | 36 +--
.../reference/builder/member/transparent.md | 20 +-
website/src/reference/builder/member/with.md | 2 +-
.../builder/top-level/builder_type.md | 2 +-
.../src/reference/builder/top-level/crate.md | 4 +-
.../src/reference/builder/top-level/derive.md | 2 +-
.../reference/builder/top-level/finish_fn.md | 2 +-
website/src/reference/builder/top-level/on.md | 2 +-
.../reference/builder/top-level/start_fn.md | 2 +-
36 files changed, 508 insertions(+), 513 deletions(-)
delete mode 100644 README.v2.md
create mode 100644 README.v3.md
rename website/src/guide/{typestate-api => }/typestate-api.md (73%)
diff --git a/README.md b/README.md
index ed406897..3e3903bd 100644
--- a/README.md
+++ b/README.md
@@ -1,11 +1,15 @@
+
-
+`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](https://bon-rs.com/guide/overview).
-
+## Quick examples
-# Overview
+### Builder for a free function
-`bon` is a Rust crate for generating compile-time-checked builders for structs and functions. It also provides idiomatic partial application with optional and named parameters for functions and methods.
-
-If you wonder "Why would I use builders?", see the [motivational blog post](https://bon-rs.com/blog/how-to-do-named-function-arguments-in-rust).
-
-## Function Builder
-
-You can turn a function with positional parameters into a function with named parameters with `#[builder]`.
+You can turn a function with positional parameters into a function with named parameters just by placing the `#[builder]` attribute on top of it.
```rust
use bon::builder;
@@ -74,44 +60,9 @@ let greeting = greet()
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.
-
-## Struct Builder
-
-Use `#[derive(Builder)]` to generate a builder for a struct.
-
-```rust
-use bon::Builder;
-
-#[derive(Builder)]
-struct User {
- name: String,
- is_admin: bool,
- level: Option,
-}
-
-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);
-```
-
-## Method Builder
-
-Associated methods require `#[bon]` on top of the impl block additionally.
+### Builder for an associated method
-### Method `new`
-
-The method named `new` generates `builder()/build()` methods.
+For associated methods you also need to add the `#[bon]` macro on top of the impl block.
```rust
use bon::bon;
@@ -121,115 +72,74 @@ struct User {
name: String,
}
-#[bon]
+#[bon] // <- this attribute is required on impl blocks that contain `#[builder]`
impl User {
#[builder]
fn new(id: u32, name: String) -> Self {
Self { id, name }
}
-}
-
-let user = User::builder()
- .id(1)
- .name("Bon".to_owned())
- .build();
-
-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/compatibility#switching-between-derive-builder-and-builder-on-the-new-method) page).
-
-### Other Methods
-All other methods generate `{method_name}()/call()` methods.
-
-```rust
-use bon::bon;
-
-struct Greeter {
- name: String,
-}
-
-#[bon]
-impl Greeter {
#[builder]
- fn greet(&self, target: &str, prefix: Option<&str>) -> String {
- let prefix = prefix.unwrap_or("INFO");
+ fn greet(&self, target: &str, level: Option<&str>) -> String {
+ let level = level.unwrap_or("INFO");
let name = &self.name;
- format!("[{prefix}] {name} says hello to {target}")
+ format!("[{level}] {name} says hello to {target}")
}
}
-let greeter = Greeter { name: "Bon".to_owned() };
+// The method named `new` generates `builder()/build()` methods
+let user = User::builder()
+ .id(1)
+ .name("Bon".to_owned())
+ .build();
-let greeting = greeter
+// All other methods generate `method_name()/call()` methods
+let greeting = user
.greet()
.target("the world")
- // `prefix` is optional, omitting it is fine
+ // `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");
```
-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.
-
-| ⭐ Don't forget to give our repo a [star on Github ⭐](https://github.com/elastio/bon)! |
-| --- |
+### Builder for a struct
-## What's Next?
+The `#[derive(Builder)]` macro generates a builder for a struct.
-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/optional-members) with the optional/default values topic. 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.
-
-The [🔍 API Reference](https://bon-rs.com/reference/builder) will help you navigate the attributes once you feel comfortable with the basics of `bon`. Both `#[derive(Builder)]` on structs and `#[builder]` on functions/methods have almost identical attributes API, so the documentation for them is common.
+```rust
+use bon::Builder;
-## Installation
+#[derive(Builder)]
+struct User {
+ name: String,
+ is_admin: bool,
+ level: Option,
+}
-Add `bon` to your `Cargo.toml`.
+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();
-```toml
-[dependencies]
-bon = "2.3"
+assert_eq!(user.name, "Bon");
+assert_eq!(user.level, Some(24));
+assert!(user.is_admin);
```
-You can opt out of `std` and `alloc` cargo features with `default-features = false` for `no_std` environments.
-
-## 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).
+See [the guide](https://bon-rs.com/guide/overview) for more.
-## Socials
+---
+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](https://github.com/elastio/bon). Any support and contribution are appreciated 🐱!
-
-
-`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](https://bon-rs.com/guide/overview).
-
-## 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.
-
-```rust
-use bon::builder;
-
-#[builder]
-fn greet(name: &str, level: Option) -> 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.
-
-```rust
-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.
-
-```rust
-use bon::Builder;
-
-#[derive(Builder)]
-struct User {
- name: String,
- is_admin: bool,
- level: Option,
-}
-
-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](https://bon-rs.com/guide/overview) 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](https://github.com/elastio/bon). 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.
-
diff --git a/README.v3.md b/README.v3.md
new file mode 100644
index 00000000..3071ffb0
--- /dev/null
+++ b/README.v3.md
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+# Overview
+
+`bon` is a Rust crate for generating compile-time-checked builders for structs and functions. It also provides idiomatic partial application with optional and named parameters for functions and methods.
+
+If you wonder "Why would I use builders?", see the [motivational blog post](https://bon-rs.com/blog/how-to-do-named-function-arguments-in-rust).
+
+## Function Builder
+
+You can turn a function with positional parameters into a function with named parameters with `#[builder]`.
+
+```rust
+use bon::builder;
+
+#[builder]
+fn greet(name: &str, level: Option) -> 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");
+```
+
+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.
+
+## Struct Builder
+
+Use `#[derive(Builder)]` to generate a builder for a struct.
+
+```rust
+use bon::Builder;
+
+#[derive(Builder)]
+struct User {
+ name: String,
+ is_admin: bool,
+ level: Option,
+}
+
+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);
+```
+
+## Method Builder
+
+Associated methods require `#[bon]` on top of the impl block additionally.
+
+### Method `new`
+
+The method named `new` generates `builder()/build()` methods.
+
+```rust
+use bon::bon;
+
+struct User {
+ id: u32,
+ name: String,
+}
+
+#[bon]
+impl User {
+ #[builder]
+ fn new(id: u32, name: String) -> Self {
+ Self { id, name }
+ }
+}
+
+let user = User::builder()
+ .id(1)
+ .name("Bon".to_owned())
+ .build();
+
+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).
+
+### Other Methods
+
+All other methods generate `{method_name}()/call()` methods.
+
+```rust
+use bon::bon;
+
+struct Greeter {
+ name: String,
+}
+
+#[bon]
+impl Greeter {
+ #[builder]
+ fn greet(&self, target: &str, prefix: Option<&str>) -> String {
+ let prefix = prefix.unwrap_or("INFO");
+ let name = &self.name;
+
+ format!("[{prefix}] {name} says hello to {target}")
+ }
+}
+
+let greeter = Greeter { name: "Bon".to_owned() };
+
+let greeting = greeter
+ .greet()
+ .target("the world")
+ // `prefix` is optional, omitting it is fine
+ .call();
+
+assert_eq!(greeting, "[INFO] Bon says hello to the world");
+```
+
+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.
+
+| ⭐ 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 🐱!
+
+Feel free to jump to code and use the `#[builder]` and `#[derive(Builder)]` once you've seen enough docs to get started.
+
+The [🔍 API Reference](https://bon-rs.com/reference/builder) will help you navigate the attributes once you feel comfortable with the basics of `bon`. Both `#[derive(Builder)]` on structs and `#[builder]` on functions/methods have almost identical attributes API, so the documentation for them is common.
+
+## Installation
+
+Add `bon` to your `Cargo.toml`.
+
+```toml
+[dependencies]
+bon = "2.3"
+```
+
+You can opt out of `std` and `alloc` cargo features with `default-features = false` for `no_std` environments.
+
+## 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).
+
+## Socials
+
+
+
Profile of the maintainer. There are only posts about bon and Rust in general here.
+
+
+
+
+## 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
+
+
+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.
+
+
+
diff --git a/bon-macros/src/builder/builder_gen/state_mod.rs b/bon-macros/src/builder/builder_gen/state_mod.rs
index 9f2d38fc..e380d95a 100644
--- a/bon-macros/src/builder/builder_gen/state_mod.rs
+++ b/bon-macros/src/builder/builder_gen/state_mod.rs
@@ -234,8 +234,7 @@ impl<'a> StateModGenCtx<'a> {
let docs = format!(
"Marker trait that indicates that all required members are set.\n\n\
In this state, you can finish building by calling the method \
- [`{builder_ident}::{finish_fn}()`](super::{builder_ident}::{finish_fn}()).
- ",
+ [`{builder_ident}::{finish_fn}()`](super::{builder_ident}::{finish_fn}())",
);
quote! {
diff --git a/bon/src/__/ide.rs b/bon/src/__/ide.rs
index ae649b52..59ddcb50 100644
--- a/bon/src/__/ide.rs
+++ b/bon/src/__/ide.rs
@@ -8,93 +8,93 @@
pub mod builder_top_level {
use super::*;
- /// See the docs at
+ /// See the docs at
pub const builder_type: Option = None;
pub mod builder_type {
use super::*;
- /// See the docs at
+ /// See the docs at
pub const name: Identifier = Identifier;
- /// See the docs at
+ /// See the docs at
pub const vis: VisibilityString = VisibilityString;
- /// See the docs at
+ /// See the docs at
pub const doc: DocComments = DocComments;
}
- /// See the docs at
+ /// See the docs at
pub const finish_fn: Option = None;
- /// See the docs at
+ /// See the docs at
pub mod finish_fn {
use super::*;
- /// See the docs at
+ /// See the docs at
pub const name: Identifier = Identifier;
- /// See the docs at
+ /// See the docs at
pub const vis: VisibilityString = VisibilityString;
- /// See the docs at
+ /// See the docs at
pub const doc: DocComments = DocComments;
}
- /// See the docs at
+ /// See the docs at
pub const start_fn: Option = None;
- /// See the docs at
+ /// See the docs at
pub mod start_fn {
use super::*;
- /// See the docs at
+ /// See the docs at
pub const name: Identifier = Identifier;
- /// See the docs at
+ /// See the docs at
pub const vis: VisibilityString = VisibilityString;
- /// See the docs at
+ /// See the docs at
pub const doc: DocComments = DocComments;
}
- /// See the docs at
+ /// See the docs at
pub const state_mod: Option = None;
- /// See the docs at
+ /// See the docs at
pub mod state_mod {
use super::*;
- /// See the docs at
+ /// See the docs at
pub const name: Identifier = Identifier;
- /// See the docs at
+ /// See the docs at
pub const vis: VisibilityString = VisibilityString;
- /// See the docs at
+ /// See the docs at
pub const doc: DocComments = DocComments;
}
- /// See the docs at
+ /// See the docs at
pub mod on {
use super::*;
- /// See the docs at
+ /// See the docs at
pub const into: Flag = Flag;
- /// See the docs at
+ /// See the docs at
pub const transparent: Flag = Flag;
- /// See the docs at
+ /// See the docs at
pub const overwritable: Flag = Flag;
}
- /// See the docs at
+ /// See the docs at
pub mod derive {
- /// See the docs at
+ /// See the docs at
pub use core::fmt::Debug;
- /// See the docs at
+ /// See the docs at
pub use core::clone::Clone;
}
@@ -102,7 +102,7 @@ pub mod builder_top_level {
/// It's hinted with an underscore due to the limitations of the current
/// completions limitation. This will be fixed in the future.
///
- /// See the docs at
+ /// See the docs at
pub const crate_: Option = None;
}
diff --git a/bon/src/examples/comprehensive.rs b/bon/src/examples/comprehensive.rs
index 77a2a714..4333f590 100644
--- a/bon/src/examples/comprehensive.rs
+++ b/bon/src/examples/comprehensive.rs
@@ -1,11 +1,11 @@
//! Comprehensive example of the generated builder and its typestate API.
//!
-//! The preliminary reading of [Builder Extensions](https://bon-rs.com/guide/builder-extensions)
+//! The preliminary reading of [Typestate API](https://bon-rs.com/guide/typestate-api)
//! guide is recommended to understand how the pieces in this example fit together.
//!
//! This module contains a struct [`Example`] that was annotated with [`#[derive(Builder)]`](crate::Builder).
-//! The config [`#[builder(state_mod(vis = "pub"))]`](https://bon-rs.com/reference/builder/top-level/state_mod) was also applied to make
-//! the generated builder's typestate API public and visible here in the docs.
+//! The config [`#[builder(state_mod(vis = "pub"))]`](https://bon-rs.com/reference/builder/top-level/state_mod)
+//! was applied to make the generated builder's typestate API public and visible here in the docs.
//!
//! The following was generated by the macro:
//! - [`ExampleBuilder`] - the builder struct itself
diff --git a/bon/src/examples/minimal.rs b/bon/src/examples/minimal.rs
index 7b648813..751c9fb9 100644
--- a/bon/src/examples/minimal.rs
+++ b/bon/src/examples/minimal.rs
@@ -1,15 +1,14 @@
//! Minimal example of the generated builder and its typestate API.
//!
-//! This documentation was generated as a showcase for the [Builder Extensions]
+//! This documentation was generated as a showcase for the [Builder's Type Signature]
//! guide
//!
-//! [Builder Extensions]: https://bon-rs.com/guide/builder-extensions#builder-type-signature
+//! [Builder's Type Signature]: https://bon-rs.com/guide/typestate-api/builders-type-signature
/// Example struct with the `#[derive(Builder)]` annotation.
#[derive(crate::Builder)]
#[builder(crate = crate, state_mod(vis = "pub"))]
pub struct Example {
- /// Example required member
x1: u32,
x2: u32,
}
diff --git a/website/.vitepress/config.mts b/website/.vitepress/config.mts
index abe63cdd..aeaa51c0 100644
--- a/website/.vitepress/config.mts
+++ b/website/.vitepress/config.mts
@@ -63,7 +63,7 @@ export default defineConfig({
markdown: {
languageAlias: {
- // Attributes highlighting works with better JS tokenizer 😳
+ // Attributes highlighting works better with JS tokenizer 😳
attr: "js",
},
@@ -84,10 +84,6 @@ export default defineConfig({
srcDir: "src",
- rewrites: {
- "guide/:subdir/:page": "guide/:page",
- },
-
// https://vitepress.dev/reference/default-theme-config
themeConfig: {
logo: "/bon-logo-thumb.png",
@@ -139,27 +135,27 @@ export default defineConfig({
items: [
{
text: "Optional Members",
- link: "/guide/optional-members",
+ link: "/guide/basics/optional-members",
},
{
text: "Into Conversions",
- link: "/guide/into-conversions",
+ link: "/guide/basics/into-conversions",
},
{
text: "Custom Conversions",
- link: "/guide/custom-conversions",
+ link: "/guide/basics/custom-conversions",
},
{
text: "Positional Members",
- link: "/guide/positional-members",
+ link: "/guide/basics/positional-members",
},
{
text: "Inspecting",
- link: "/guide/inspecting",
+ link: "/guide/basics/inspecting",
},
{
text: "Documenting",
- link: "/guide/documenting",
+ link: "/guide/basics/documenting",
},
],
},
@@ -169,11 +165,11 @@ export default defineConfig({
items: [
{
text: "Builder's Type Signature",
- link: "/guide/builders-type-signature",
+ link: "/guide/typestate-api/builders-type-signature",
},
{
text: "Custom Methods",
- link: "/guide/custom-methods",
+ link: "/guide/typestate-api/custom-methods",
}
],
},
@@ -182,19 +178,19 @@ export default defineConfig({
items: [
{
text: "Conditional Building",
- link: "/guide/conditional-building",
+ link: "/guide/patterns/conditional-building",
},
{
text: "Fallible Builders",
- link: "/guide/fallible-builders",
+ link: "/guide/patterns/fallible-builders",
},
{
text: "Into Conversions In-Depth",
- link: "/guide/into-conversions-in-depth",
+ link: "/guide/patterns/into-conversions-in-depth",
},
{
text: "Shared Configuration",
- link: "/guide/shared-configuration",
+ link: "/guide/patterns/shared-configuration",
},
],
},
@@ -203,23 +199,23 @@ export default defineConfig({
items: [
{
text: "Compatibility",
- link: "/guide/compatibility",
+ link: "/guide/misc/compatibility",
},
{
text: "Limitations",
- link: "/guide/limitations",
+ link: "/guide/misc/limitations",
},
{
text: "Benchmarks",
- link: "/guide/benchmarks",
+ link: "/guide/misc/benchmarks",
},
{
text: "Alternatives",
- link: "/guide/alternatives",
+ link: "/guide/misc/alternatives",
},
{
text: "Troubleshooting",
- link: "/guide/troubleshooting",
+ link: "/guide/misc/troubleshooting",
},
],
},
@@ -228,7 +224,7 @@ export default defineConfig({
items: [
{
text: "Contributing",
- link: "/guide/contributing",
+ link: "/guide/internal/contributing",
},
],
},
diff --git a/website/package-lock.json b/website/package-lock.json
index bbaecf30..cacbda17 100644
--- a/website/package-lock.json
+++ b/website/package-lock.json
@@ -18,10 +18,9 @@
"htmlparser2": "^9.1.0",
"leven": "^4.0.0",
"medium-zoom": "^1.1.0",
- "smol-toml": "^1.3.0",
"ts-node": "^10.9.2",
"ts-pattern": "^5.5.0",
- "vitepress": "^1.4.3"
+ "vitepress": "^1.4.5"
}
},
"node_modules/@algolia/autocomplete-core": {
@@ -2671,18 +2670,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/smol-toml": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.3.0.tgz",
- "integrity": "sha512-tWpi2TsODPScmi48b/OQZGi2lgUmBCHy6SZrhi/FdnnHiU1GwebbCfuQuxsC3nHaLwtYeJGPrDZDIeodDOc4pA==",
- "dev": true,
- "engines": {
- "node": ">= 18"
- },
- "funding": {
- "url": "https://github.com/sponsors/cyyynthia"
- }
- },
"node_modules/source-map-js": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
@@ -3019,9 +3006,9 @@
}
},
"node_modules/vitepress": {
- "version": "1.4.3",
- "resolved": "https://registry.npmjs.org/vitepress/-/vitepress-1.4.3.tgz",
- "integrity": "sha512-956c2K2Mr0ubY9bTc2lCJD3g0mgo0mARB1iJC/BqUt4s0AM8Wl60wSU4zbFnzV7X2miFK1XJDKzGZnuEN90umw==",
+ "version": "1.4.5",
+ "resolved": "https://registry.npmjs.org/vitepress/-/vitepress-1.4.5.tgz",
+ "integrity": "sha512-9K0k8kvdEbeowVCpKF/x0AySSq0Pr9pM8xufLgQcKMjsifwxtDjXJjcFhZv4LYw2dcpdYiBq2j7PnWi0tCaMCg==",
"dev": true,
"dependencies": {
"@docsearch/css": "^3.6.2",
diff --git a/website/package.json b/website/package.json
index fd2e3734..51a11a5f 100644
--- a/website/package.json
+++ b/website/package.json
@@ -17,10 +17,9 @@
"htmlparser2": "^9.1.0",
"leven": "^4.0.0",
"medium-zoom": "^1.1.0",
- "smol-toml": "^1.3.0",
"ts-node": "^10.9.2",
"ts-pattern": "^5.5.0",
- "vitepress": "^1.4.3"
+ "vitepress": "^1.4.5"
},
"dependencies": {
"vue": "^3.5.12"
diff --git a/website/src/guide/basics/custom-conversions.md b/website/src/guide/basics/custom-conversions.md
index 2ff41146..84696a33 100644
--- a/website/src/guide/basics/custom-conversions.md
+++ b/website/src/guide/basics/custom-conversions.md
@@ -2,7 +2,7 @@
[`#[builder(into)]`](../../reference/builder/member/into) is great and it works in many cases. However, what if you need to do a conversion that isn't a simple `Into`? What if you want your setter to accept several parameters? What if your setter should be fallible? The answer to all these questions is the bigger brother [`#[builder(with)]`](../../reference/builder/member/with).
-You can pass a custom closure to `#[builder(with)]`. It will be used to define the signature of the setter and perform a conversion.
+You can pass a custom closure to `#[builder(with)]`. It will define the signature of the setter and perform a conversion.
```rust
use bon::Builder;
diff --git a/website/src/guide/basics/documenting.md b/website/src/guide/basics/documenting.md
index bc5df75c..6413a496 100644
--- a/website/src/guide/basics/documenting.md
+++ b/website/src/guide/basics/documenting.md
@@ -27,7 +27,7 @@ fn greet(
::: details How does this work? 🤔
-This works because Rust compiler checks for invalid placement of `#[doc = ...]` attributes only after the macro expansion stage. `#[builder]` makes sure to remove the docs from the function's arguments in the expanded code, and instead moves them to the docs on setter methods.
+This works because Rust compiler checks for invalid placement of `#[doc = ...]` attributes only after the macro expansion stage. `#[builder]` removes the docs from the function's arguments in the expanded code, and instead moves them to the docs on setter methods.
:::
@@ -48,6 +48,7 @@ use bon::Builder;
start_fn(doc {
/// Custom docs on the starting function
}),
+ // ...
)]
struct Example {}
```
@@ -59,7 +60,7 @@ You can document the following items this way:
| [`builder_type`](../../reference/builder/top-level/builder_type#doc) | Builder struct
| [`start_fn`](../../reference/builder/top-level/start_fn#doc) | Starting function
| [`finish_fn`](../../reference/builder/top-level/finish_fn#doc) | Finishing function
-| [`state_mod`](../../reference/builder/top-level/state_mod#doc) | Builder state API module (more details in [Builder Extensions](../advanced/builder-extensions))
+| [`state_mod`](../../reference/builder/top-level/state_mod#doc) | Builder state API module (more details in [Typestate API](../typestate-api))
| [`setters`](../../reference/builder/member/setters#doc) | Custom docs for setters. Prevents copying them from the field/argument
diff --git a/website/src/guide/basics/into-conversions.md b/website/src/guide/basics/into-conversions.md
index a57b6a26..09c22047 100644
--- a/website/src/guide/basics/into-conversions.md
+++ b/website/src/guide/basics/into-conversions.md
@@ -47,4 +47,4 @@ Project::builder()
.build();
```
-`Into` conversions don't always make sense, and you should be aware of their downsides as well. The article ["Into Conversions In-Depth"](./into-conversions-in-depth) provides recommendations on when it makes sense to use and to avoid `Into` conversions.
+`Into` conversions don't always make sense, and you should be aware of their downsides as well. The article [Into Conversions In-Depth](../patterns/into-conversions-in-depth) provides recommendations on when it makes sense to use and to avoid `Into` conversions.
diff --git a/website/src/guide/basics/optional-members.md b/website/src/guide/basics/optional-members.md
index ad61fb23..1e6324c4 100644
--- a/website/src/guide/basics/optional-members.md
+++ b/website/src/guide/basics/optional-members.md
@@ -30,7 +30,7 @@ The builder provides a **pair** of setters for each optional member:
[setters]: ../reference/builder/member/setters
-::: details See how the setters look like in the generated code
+::: details See how the setters look in the generated code
```rust ignore
// [GENERATED CODE (simplified)]
@@ -109,6 +109,8 @@ let result = example()
.call();
```
+You can also reference other members in the default expression. See [`#[builder(default)]`](../../reference/builder/member/default#evaluation-context) reference for details.
+
## Conditional building
-Now that you know how optional members work you can check out the ["Conditional building" design patterns](./conditional-building) or continue studying other features of `bon` by following the "Next page" link at the bottom.
+Now that you know how optional members work you can check out the [Conditional building](../patterns/conditional-building) design patterns or continue studying other features of `bon` by following the "Next page" link at the bottom.
diff --git a/website/src/guide/basics/positional-members.md b/website/src/guide/basics/positional-members.md
index 8910aa7a..a44741a6 100644
--- a/website/src/guide/basics/positional-members.md
+++ b/website/src/guide/basics/positional-members.md
@@ -1,6 +1,6 @@
# Positional Members
-You can let the caller pass some values as positional parameters to the starting function that creates the builder or to the finishing function that consumes it.
+You can let the caller pass some values as positional parameters to the starting function, that creates the builder or to the finishing function, that consumes it.
## Starting function
@@ -42,7 +42,7 @@ They have different meanings.
## Finishing function
-Use `#[builder(finish_fn)]` to move some members to the parameters of the starting function.
+Use `#[builder(finish_fn)]` to move some members to the parameters of the finishing function.
```rust
use bon::Builder;
diff --git a/website/src/guide/patterns/conditional-building.md b/website/src/guide/patterns/conditional-building.md
index 68c72bc6..22fb9952 100644
--- a/website/src/guide/patterns/conditional-building.md
+++ b/website/src/guide/patterns/conditional-building.md
@@ -2,7 +2,7 @@
On this page, we'll review a case when you have multiple branches in your code that need to set different values for different builder members.
-Since builders generated by `bon` use the type-state pattern and setters consume `self`, it is a bit more complicated for conditional code to use them. But, not until you know the patterns described below 🐱. So let's learn how to write better conditional code 📚.
+Since builders generated by `bon` use the typestate pattern and setters consume `self`, it is a bit more complicated for conditional code to use them. But, not until you know the patterns described below 🐱. So let's learn how to write better conditional code 📚.
The patterns described here aren't mutually exclusive. You can combine them as you see necessary to keep your code clean.
@@ -58,7 +58,7 @@ Once the `build()` method is called, we no longer have the context of how exactl
## Shared total builder
-In contrast to the [shared partial builder](#shared-partial-builder), here we are going to use the builder strictly _after_ the conditional code. The conditional code needs to create the variables that hold the component values for the builder beforehand.
+In contrast to the [shared partial builder](#shared-partial-builder), here we'll use the builder strictly _after_ the conditional code. The conditional code needs to create the variables that hold the component values for the builder beforehand.
**Example:**
@@ -108,7 +108,7 @@ In this case, we create a variable for each conditional member beforehand and in
::: tip NOTE
-Creating separate variables is not strictly required. You can inline the usages of variables in such a simple code like here, where each branch of the `if` takes a single line. Anyhow, branches can be much bigger in real code.
+Creating separate variables is not strictly required. You can inline the usages of variables in such simple code as here, where each branch of the `if` takes a single line. Anyhow, branches can be much bigger in real code.
:::
diff --git a/website/src/guide/patterns/shared-configuration.md b/website/src/guide/patterns/shared-configuration.md
index 57c4b2c9..349a3cee 100644
--- a/website/src/guide/patterns/shared-configuration.md
+++ b/website/src/guide/patterns/shared-configuration.md
@@ -10,7 +10,7 @@ On this page, you'll learn how to share common configurations for builders to av
As an example, let's suppose you want to enable [`Into` conversions](./into-conversions-in-depth) for specific types across all your builders and maybe also override the name of the finishing function that consumes the builder from the default `build` to `finish`.
-The problem that you'll quickly run into is that you'll need to repeat the same configuration for every usage of the builder macro.
+You'll quickly run into a problem, where you need to repeat the same configuration for every usage of the builder macro.
```rust
use bon::Builder;
@@ -43,7 +43,7 @@ This code uses the [`#[builder(on(...))]`](../reference/builder/top-level/on) at
To overcome this problem you can utilize the [`macro_rules_attribute`] crate. It allows you to declare an [`attribute_alias`](https://docs.rs/macro_rules_attribute/latest/macro_rules_attribute/macro.attribute_alias.html) that defines all the shared configuration for your builders and makes it reusable.
-Use this approach if you have a lot of structs/functions in your crate that need a builder
+Use this approach if you have a lot of structs/functions in your crate that need a builder.
### Structs
diff --git a/website/src/guide/typestate-api/typestate-api.md b/website/src/guide/typestate-api.md
similarity index 73%
rename from website/src/guide/typestate-api/typestate-api.md
rename to website/src/guide/typestate-api.md
index dce76a7e..11f6730d 100644
--- a/website/src/guide/typestate-api/typestate-api.md
+++ b/website/src/guide/typestate-api.md
@@ -1,6 +1,6 @@
# Typestate API
-This section will teach you the builder's typestate API. It'll describe the underlying component traits and types of the builder type and how to use them.
+This section teaches you the builder's typestate API. It describes the underlying component traits and types of the builder type and how to use them.
Reading this is optional. The typestate API is private by default. The users of your builder can't denote its type unless you enable [`#[builder(state_mod(vis = "pub"))]`](../../reference/builder/top-level/state_mod).
diff --git a/website/src/guide/typestate-api/builders-type-signature.md b/website/src/guide/typestate-api/builders-type-signature.md
index 2aec904f..db40d891 100644
--- a/website/src/guide/typestate-api/builders-type-signature.md
+++ b/website/src/guide/typestate-api/builders-type-signature.md
@@ -12,11 +12,11 @@ It can also be overridden with [`#[builder(builder_type = NewName)]`](../../refe
## Generic Typestate Parameter
-Builders generated by `bon` macros use the typestate pattern. Every time you call a setter the builder's type changes. The builder's typestate doesn't depend on the syntax from which it was generated (struct or function).
+Builders generated by `bon` macros use the typestate pattern. The builder's typestate doesn't depend on the syntax from which it was generated (struct or function).
-The builder always contains a generic parameter `S` (stands for "state") at the end. This parameter holds the type state that describes what members were set in the builder.
+Every time you call a setter the builder's type changes. The builder always contains a generic parameter `S` (stands for "state") at the end. This parameter holds the type state that describes what members were set in the builder.
-It's probably easier to understand with an example. Don't worry, the next paragraph will explain it.
+It's probably easier to understand with an example. Don't worry, the next paragraph will explain everything.
```rust
use bon::Builder;
@@ -45,7 +45,7 @@ The type states come from the builder's state module. The name of that module is
## Visibility
-The type state module is private by default, and only accessible within the module where the builder macro was used. This way the builder type becomes unnameable outside of the module where it was generated.
+The type state module is private by default and only accessible within the module where the builder macro was used. Thus, the builder type becomes unnameable outside of the module where it was generated.
If you want to expose your builder's type signature, you need to add [`#[builder(state_mod(vis = "..."))]`](../../reference/builder/top-level/state_mod), where `...` can be `pub` or `pub(crate)` or any other visibility you want to expose the state module under.
diff --git a/website/src/guide/typestate-api/custom-methods.md b/website/src/guide/typestate-api/custom-methods.md
index f978829f..15b8acc6 100644
--- a/website/src/guide/typestate-api/custom-methods.md
+++ b/website/src/guide/typestate-api/custom-methods.md
@@ -1,4 +1,4 @@
# Custom Methods
-- add custom methods to the builder type 💪
+- TODO: add custom methods to the builder type 💪
diff --git a/website/src/reference/builder/member/default.md b/website/src/reference/builder/member/default.md
index 0810fc17..a7d7887b 100644
--- a/website/src/reference/builder/member/default.md
+++ b/website/src/reference/builder/member/default.md
@@ -1,6 +1,6 @@
# `default`
-**Applies to:**
+**Applies to:**
Makes the member optional and assigns a default value to it. The default value is lazily computed inside of the finishing function based on the form of this attribute.
@@ -39,31 +39,31 @@ use bon::Builder;
#[derive(Builder)]
struct Example {
#[builder(default)] // [!code highlight]
- foo: u32,
+ x1: u32,
#[builder(default = "anon".to_owned())] // [!code highlight]
- bar: String,
+ x2: String,
// No need for `.to_owned()`. Into is applied to the expression
#[builder(default = "bon", into)] // [!code highlight]
- baz: String,
+ x3: String,
}
let value = Example::builder().build();
-assert_eq!(value.foo, 0);
-assert_eq!(value.bar, "anon");
-assert_eq!(value.baz, "bon");
+assert_eq!(value.x1, 0);
+assert_eq!(value.x2, "anon");
+assert_eq!(value.x3, "bon");
let value = Example::builder()
- .foo(99)
- .maybe_bar(None) // None means the default will be used
- .maybe_baz(Some("lyra"))
+ .x1(99)
+ .maybe_x2(None) // None means the default will be used
+ .maybe_x3(Some("lyra"))
.build();
-assert_eq!(value.foo, 99);
-assert_eq!(value.bar, "anon");
-assert_eq!(value.baz, "lyra");
+assert_eq!(value.x1, 99);
+assert_eq!(value.x2, "anon");
+assert_eq!(value.x3, "lyra");
```
```rust [Function]
@@ -72,16 +72,16 @@ use bon::builder;
#[builder]
fn example(
#[builder(default)] // [!code highlight]
- foo: u32,
+ x1: u32,
#[builder(default = "anon".to_owned())] // [!code highlight]
- bar: String,
+ x2: String,
// No need for `.to_owned()`. Into is applied to the expression
#[builder(default = "bon", into)] // [!code highlight]
- baz: String,
+ x3: String,
) -> (u32, String, String) {
- (foo, bar, baz)
+ (x1, x2, x3)
}
let value = example().call();
@@ -91,9 +91,9 @@ assert_eq!(value.1, "anon");
assert_eq!(value.2, "bon");
let value = example()
- .foo(99)
- .maybe_bar(None) // None means the default will be used
- .maybe_baz(Some("lyra"))
+ .x1(99)
+ .maybe_x2(None) // None means the default will be used
+ .maybe_x3(Some("lyra"))
.call();
assert_eq!(value.0, 99);
@@ -105,9 +105,9 @@ assert_eq!(value.2, "lyra");
use bon::bon;
struct Example {
- foo: u32,
- bar: String,
- baz: String,
+ x1: u32,
+ x2: String,
+ x3: String,
}
#[bon]
@@ -115,34 +115,34 @@ impl Example {
#[builder]
fn new(
#[builder(default)] // [!code highlight]
- foo: u32,
+ x1: u32,
#[builder(default = "anon".to_owned())] // [!code highlight]
- bar: String,
+ x2: String,
// No need for `.to_owned()`. Into is applied to the expression
#[builder(default = "bon", into)] // [!code highlight]
- baz: String,
+ x3: String,
) -> Self {
- Self { foo, bar, baz }
+ Self { x1, x2, x3 }
}
}
let value = Example::builder().build();
-assert_eq!(value.foo, 0);
-assert_eq!(value.bar, "anon");
-assert_eq!(value.baz, "bon");
+assert_eq!(value.x1, 0);
+assert_eq!(value.x2, "anon");
+assert_eq!(value.x3, "bon");
let value = Example::builder()
- .foo(99)
- .maybe_bar(None) // None means the default will be used
- .maybe_baz(Some("lyra"))
+ .x1(99)
+ .maybe_x2(None) // None means the default will be used
+ .maybe_x3(Some("lyra"))
.build();
-assert_eq!(value.foo, 99);
-assert_eq!(value.bar, "anon");
-assert_eq!(value.baz, "lyra");
+assert_eq!(value.x1, 99);
+assert_eq!(value.x2, "anon");
+assert_eq!(value.x3, "lyra");
```
:::
@@ -158,24 +158,24 @@ use bon::Builder;
#[derive(Builder)]
struct Example {
- foo: u32,
+ x1: u32,
- // Note that here we don't have access to `baz`
+ // Note that here we don't have access to `x3`
// because it's declared (and thus initialized) later
- #[builder(default = 2 * foo)]
- bar: u32,
+ #[builder(default = 2 * x1)]
+ x2: u32,
- #[builder(default = bar + foo)]
- baz: u32,
+ #[builder(default = x2 + x1)]
+ x3: u32,
}
let value = Example::builder()
- .foo(3)
+ .x1(3)
.build();
-assert_eq!(value.foo, 3);
-assert_eq!(value.bar, 6);
-assert_eq!(value.baz, 9);
+assert_eq!(value.x1, 3);
+assert_eq!(value.x2, 6);
+assert_eq!(value.x3, 9);
```
```rust [Function]
@@ -183,21 +183,21 @@ use bon::builder;
#[builder]
fn example(
- foo: u32,
+ x1: u32,
- // Note that here we don't have access to `baz`
+ // Note that here we don't have access to `x3`
// because it's declared (and thus initialized) later
- #[builder(default = 2 * foo)]
- bar: u32,
+ #[builder(default = 2 * x1)]
+ x2: u32,
- #[builder(default = bar + foo)]
- baz: u32,
+ #[builder(default = x2 + x1)]
+ x3: u32,
) -> (u32, u32, u32) {
- (foo, bar, baz)
+ (x1, x2, x3)
}
let value = example()
- .foo(3)
+ .x1(3)
.call();
assert_eq!(value, (3, 6, 9));
@@ -212,22 +212,22 @@ struct Example;
impl Example {
#[builder]
fn example(
- foo: u32,
+ x1: u32,
- // Note that here we don't have access to `baz`
+ // Note that here we don't have access to `x3`
// because it's declared (and thus initialized) later
- #[builder(default = 2 * foo)]
- bar: u32,
+ #[builder(default = 2 * x1)]
+ x2: u32,
- #[builder(default = bar + foo)]
- baz: u32,
+ #[builder(default = x2 + x1)]
+ x3: u32,
) -> (u32, u32, u32) {
- (foo, bar, baz)
+ (x1, x2, x3)
}
}
let value = Example::example()
- .foo(3)
+ .x1(3)
.call();
assert_eq!(value, (3, 6, 9));
diff --git a/website/src/reference/builder/member/finish_fn.md b/website/src/reference/builder/member/finish_fn.md
index 58b650fe..bec247dc 100644
--- a/website/src/reference/builder/member/finish_fn.md
+++ b/website/src/reference/builder/member/finish_fn.md
@@ -1,6 +1,6 @@
# `finish_fn`
-**Applies to:**
+**Applies to:**
Makes the member a positional argument on the finishing function.
@@ -18,21 +18,21 @@ use bon::Builder;
#[derive(Builder)]
struct Example {
#[builder(finish_fn)] // [!code highlight]
- foo: u32,
+ x1: u32,
#[builder(finish_fn)] // [!code highlight]
- bar: u32,
+ x2: u32,
- baz: u32,
+ x3: u32,
}
let value = Example::builder()
- .baz(3)
+ .x3(3)
.build(1, 2); // [!code highlight]
-assert_eq!(value.foo, 1);
-assert_eq!(value.bar, 2);
-assert_eq!(value.baz, 3);
+assert_eq!(value.x1, 1);
+assert_eq!(value.x2, 2);
+assert_eq!(value.x3, 3);
```
```rust [Function]
@@ -41,18 +41,18 @@ use bon::builder;
#[builder]
fn example(
#[builder(finish_fn)] // [!code highlight]
- foo: u32,
+ x1: u32,
#[builder(finish_fn)] // [!code highlight]
- bar: u32,
+ x2: u32,
- baz: u32,
+ x3: u32,
) -> (u32, u32, u32) {
- (foo, bar, baz)
+ (x1, x2, x3)
}
let value = example()
- .baz(3)
+ .x3(3)
.call(1, 2); // [!code highlight]
assert_eq!(value.0, 1);
@@ -70,19 +70,19 @@ impl Example {
#[builder]
fn example(
#[builder(finish_fn)] // [!code highlight]
- foo: u32,
+ x1: u32,
#[builder(finish_fn)] // [!code highlight]
- bar: u32,
+ x2: u32,
- baz: u32,
+ x3: u32,
) -> (u32, u32, u32) {
- (foo, bar, baz)
+ (x1, x2, x3)
}
}
let value = Example::example()
- .baz(3)
+ .x3(3)
.call(1, 2); // [!code highlight]
assert_eq!(value.0, 1);
@@ -92,11 +92,11 @@ assert_eq!(value.2, 3);
:::
-You can rename the finishing function from default `build()` or `call()` to something more readable via the top-level [`#[builder(finish_fn = ...)]`](../top-level/finish-fn) attribute.
+You can rename the finishing function from default `build()` or `call()` to something more readable via the top-level [`#[builder(finish_fn = ...)]`](../top-level/finish_fn) attribute.
## Ordering
-The ordering of members annotated with `#[builder(finish_fn)]` matters! They will appear in the same order relative to each other in the finishing function signature. They must also be declared at the top of the members list strictly after members annotated with [`#[builder(start_fn)]`](./start-fn) (if any).
+The ordering of members annotated with `#[builder(finish_fn)]` matters! They will appear in the same order relative to each other in the finishing function signature. They must also be declared at the top of the members list strictly after members annotated with [`#[builder(start_fn)]`](./start_fn) (if any).
It ensures a consistent initialization order, making these members available in the evaluation context of expressions in `#[builder(default/skip = ...)]` for regular members that follow them.
diff --git a/website/src/reference/builder/member/into.md b/website/src/reference/builder/member/into.md
index 872149a5..5e89fa25 100644
--- a/website/src/reference/builder/member/into.md
+++ b/website/src/reference/builder/member/into.md
@@ -1,6 +1,6 @@
# `into`
-**Applies to:**
+**Applies to:**
::: tip
diff --git a/website/src/reference/builder/member/name.md b/website/src/reference/builder/member/name.md
index 7ba10482..a121e669 100644
--- a/website/src/reference/builder/member/name.md
+++ b/website/src/reference/builder/member/name.md
@@ -1,6 +1,6 @@
# `name`
-**Applies to:**
+**Applies to:**
Overrides the name of the member used in the builder's API. This is most useful when with struct syntax (`#[derive(Builder)]`) where you'd like to use a different name for the field internally. For functions this attribute makes less sense since it's easy to just create a variable named differently `let new_name = param_name;`. However, this attribute is still supported on function arguments.
diff --git a/website/src/reference/builder/member/overwritable.md b/website/src/reference/builder/member/overwritable.md
index 2cfb14f6..10de2795 100644
--- a/website/src/reference/builder/member/overwritable.md
+++ b/website/src/reference/builder/member/overwritable.md
@@ -1,6 +1,6 @@
# `overwritable` :microscope:
-**Applies to:**
+**Applies to:**
Allows calling setters for the same member repeatedly.
diff --git a/website/src/reference/builder/member/setters.md b/website/src/reference/builder/member/setters.md
index 185a3dff..541361c7 100644
--- a/website/src/reference/builder/member/setters.md
+++ b/website/src/reference/builder/member/setters.md
@@ -1,6 +1,6 @@
# `setters`
-**Applies to:**
+**Applies to:**
Overrides name, visibility and docs for setters.
@@ -71,7 +71,7 @@ The default name for setters is chosen according to the following rules:
| Required | `{member}`
| Optional | `some_fn` = `{member}` `option_fn` = `maybe_{member}`
-This attribute is different from [`#[builder(name)]`](./name), because it overrides only the names of setters. It doesn't influence the name of the member in the builder's [typestate API](../../../guide/advanced/builder-extensions). This attribute also has higher precedence than [`#[builder(name)]`](./name).
+This attribute is different from [`#[builder(name)]`](./name), because it overrides only the names of setters. It doesn't influence the name of the member in the builder's [typestate API](../../../guide/typestate-api). This attribute also has higher precedence than [`#[builder(name)]`](./name).
## `vis`
diff --git a/website/src/reference/builder/member/skip.md b/website/src/reference/builder/member/skip.md
index 7d12387e..d7f48bda 100644
--- a/website/src/reference/builder/member/skip.md
+++ b/website/src/reference/builder/member/skip.md
@@ -65,4 +65,4 @@ assert_eq!(example.x3, 9);
## Unsupported function syntax
-This attribute is not supported with free function or associated method syntax because it's simply unnecessary there and can easier be expressed with local variables.
+This attribute is not supported with function or method syntax because it's simply unnecessary there and can easier be expressed with local variables.
diff --git a/website/src/reference/builder/member/start_fn.md b/website/src/reference/builder/member/start_fn.md
index 02c67e15..e61e5230 100644
--- a/website/src/reference/builder/member/start_fn.md
+++ b/website/src/reference/builder/member/start_fn.md
@@ -1,6 +1,6 @@
# `start_fn`
-**Applies to:**
+**Applies to:**
Makes the member a positional argument on the starting function that creates the builder.
@@ -18,21 +18,21 @@ use bon::Builder;
#[derive(Builder)]
struct Example {
#[builder(start_fn)] // [!code highlight]
- foo: u32,
+ x1: u32,
#[builder(start_fn)] // [!code highlight]
- bar: u32,
+ x2: u32,
- baz: u32,
+ x3: u32,
}
let value = Example::builder(1, 2) // [!code highlight]
- .baz(3)
+ .x3(3)
.build();
-assert_eq!(value.foo, 1);
-assert_eq!(value.bar, 2);
-assert_eq!(value.baz, 3);
+assert_eq!(value.x1, 1);
+assert_eq!(value.x2, 2);
+assert_eq!(value.x3, 3);
```
```rust [Function]
@@ -41,18 +41,18 @@ use bon::builder;
#[builder]
fn example(
#[builder(start_fn)] // [!code highlight]
- foo: u32,
+ x1: u32,
#[builder(start_fn)] // [!code highlight]
- bar: u32,
+ x2: u32,
- baz: u32,
+ x3: u32,
) -> (u32, u32, u32) {
- (foo, bar, baz)
+ (x1, x2, x3)
}
let value = example(1, 2) // [!code highlight]
- .baz(3)
+ .x3(3)
.call();
assert_eq!(value.0, 1);
@@ -70,19 +70,19 @@ impl Example {
#[builder]
fn example(
#[builder(start_fn)] // [!code highlight]
- foo: u32,
+ x1: u32,
#[builder(start_fn)] // [!code highlight]
- bar: u32,
+ x2: u32,
- baz: u32,
+ x3: u32,
) -> (u32, u32, u32) {
- (foo, bar, baz)
+ (x1, x2, x3)
}
}
let value = Example::example(1, 2) // [!code highlight]
- .baz(3)
+ .x3(3)
.call();
assert_eq!(value.0, 1);
diff --git a/website/src/reference/builder/member/transparent.md b/website/src/reference/builder/member/transparent.md
index 0cab3111..8d57ac85 100644
--- a/website/src/reference/builder/member/transparent.md
+++ b/website/src/reference/builder/member/transparent.md
@@ -1,12 +1,12 @@
# `transparent`
-**Applies to:**
+**Applies to:**
Disables `Option` special handling, makes the member required.
::: tip
-This attribute is also configurable via the top-level [`#[builder(on(...))]`](../top-level/on). Currently, its can only be used with the `_` type pattern and as the first `on(...)` clause.
+This attribute is also configurable via the top-level [`#[builder(on(...))]`](../top-level/on). Currently, it can only be used with the `_` type pattern and as the first `on(...)` clause.
:::
@@ -20,9 +20,21 @@ use bon::Builder;
#[derive(Builder)]
struct Example {
- optional: Option,
-
#[builder(transparent)]
required: Option,
+
+ optional: Option,
}
+
+Example::builder()
+ .required(Some(2))
+ .optional(2)
+ .build();
```
+
+Notice the difference:
+
+| Member name | Setters | Comment
+|-------------|--------------------------------------------------|------------
+| `required` | `required(Option)` | Setter is required to call
+| `optional` | `optional(u32)` `maybe_optional(Option)` | Setters are optional to call
diff --git a/website/src/reference/builder/member/with.md b/website/src/reference/builder/member/with.md
index 602d3ca5..3481cd3e 100644
--- a/website/src/reference/builder/member/with.md
+++ b/website/src/reference/builder/member/with.md
@@ -1,6 +1,6 @@
# `with`
-**Applies to:**
+**Applies to:**
TODO: add docs (update the short descriptions on the parent page)
diff --git a/website/src/reference/builder/top-level/builder_type.md b/website/src/reference/builder/top-level/builder_type.md
index 71afe9d8..8ee1c999 100644
--- a/website/src/reference/builder/top-level/builder_type.md
+++ b/website/src/reference/builder/top-level/builder_type.md
@@ -4,7 +4,7 @@ outline: deep
# `builder_type`
-**Applies to:**
+**Applies to:**
Overrides name, visibility and docs for the builder struct.
diff --git a/website/src/reference/builder/top-level/crate.md b/website/src/reference/builder/top-level/crate.md
index 2fba89ed..963d7ca1 100644
--- a/website/src/reference/builder/top-level/crate.md
+++ b/website/src/reference/builder/top-level/crate.md
@@ -1,12 +1,12 @@
# `crate`
-**Applies to:** (*)
+**Applies to:** (*)
Overrides path to `bon` crate referenced in the generated code, which is useful in cases when `bon` macros are wrapped by other macros and `bon` crate is reexported.
::: info
-(*) `#[builder(crate)]` attribute isn't directly supported for associated methods. Instead, you should use the `#[bon(crate)]` attribute on top of the impl block (see examples below).
+(*) `#[builder(crate)]` attribute isn't accepted on associated methods. Instead, you should use the `#[bon(crate)]` attribute on top of the impl block (see examples below).
:::
diff --git a/website/src/reference/builder/top-level/derive.md b/website/src/reference/builder/top-level/derive.md
index aa2e5014..b8908fda 100644
--- a/website/src/reference/builder/top-level/derive.md
+++ b/website/src/reference/builder/top-level/derive.md
@@ -1,6 +1,6 @@
# `derive`
-**Applies to:**
+**Applies to:**
*⚠️ Do not confuse this with `#[derive(bon::Builder)]`⚠️*
diff --git a/website/src/reference/builder/top-level/finish_fn.md b/website/src/reference/builder/top-level/finish_fn.md
index 1e3ee77c..8b3b97cb 100644
--- a/website/src/reference/builder/top-level/finish_fn.md
+++ b/website/src/reference/builder/top-level/finish_fn.md
@@ -1,6 +1,6 @@
# `finish_fn`
-**Applies to:**
+**Applies to:**
Overrides name, visibility and docs for the finishing function.
diff --git a/website/src/reference/builder/top-level/on.md b/website/src/reference/builder/top-level/on.md
index 165baeef..7fcc694c 100644
--- a/website/src/reference/builder/top-level/on.md
+++ b/website/src/reference/builder/top-level/on.md
@@ -4,7 +4,7 @@ outline: deep
# `on`
-**Applies to:**
+**Applies to:**
Applies member attributes to all members matching a type pattern. The syntax of this attribute is `on(type_pattern, attributes)`. For example, you can automatically apply `#[builder(into)]` to all members of type `String` this way:
diff --git a/website/src/reference/builder/top-level/start_fn.md b/website/src/reference/builder/top-level/start_fn.md
index ca105b4c..9955ea37 100644
--- a/website/src/reference/builder/top-level/start_fn.md
+++ b/website/src/reference/builder/top-level/start_fn.md
@@ -1,6 +1,6 @@
# `start_fn`
-**Applies to:**
+**Applies to:**
Overrides name, visibility and docs for the starting function.
From 7bbf31933b64f72edad480012d6b6d8e6381a1b6 Mon Sep 17 00:00:00 2001
From: Veetaha
Date: Sun, 3 Nov 2024 16:40:53 +0000
Subject: [PATCH 18/18] Fix broken links
---
website/src/blog/bon-builder-generator-v2-release.md | 10 +++++-----
website/src/blog/bon-builder-v2-2-release.md | 4 ++--
website/src/blog/bon-builder-v2-3-release.md | 10 +++++-----
.../blog/how-to-do-named-function-arguments-in-rust.md | 2 +-
website/src/changelog.md | 2 +-
website/src/guide/basics/custom-conversions.md | 2 +-
website/src/guide/basics/inspecting.md | 4 ++--
website/src/guide/basics/into-conversions.md | 2 +-
website/src/guide/basics/optional-members.md | 10 +++++-----
website/src/guide/misc/alternatives.md | 6 +++---
website/src/guide/misc/compatibility.md | 4 ++--
website/src/guide/patterns/conditional-building.md | 2 +-
.../src/guide/patterns/into-conversions-in-depth.md | 2 +-
website/src/guide/patterns/shared-configuration.md | 4 ++--
website/src/guide/typestate-api.md | 2 +-
website/src/reference/builder.md | 10 +++++-----
website/src/reference/builder/member/default.md | 4 ++--
website/src/reference/builder/member/into.md | 4 ++--
website/src/reference/builder/member/overwritable.md | 6 ++----
website/src/reference/builder/member/setters.md | 6 +++---
website/src/reference/builder/member/start_fn.md | 2 +-
website/src/reference/builder/member/with.md | 2 +-
website/src/reference/builder/top-level/finish_fn.md | 2 +-
website/src/reference/builder/top-level/start_fn.md | 2 +-
website/src/reference/builder/top-level/state_mod.md | 2 ++
25 files changed, 53 insertions(+), 53 deletions(-)
diff --git a/website/src/blog/bon-builder-generator-v2-release.md b/website/src/blog/bon-builder-generator-v2-release.md
index d29e0632..d029403d 100644
--- a/website/src/blog/bon-builder-generator-v2-release.md
+++ b/website/src/blog/bon-builder-generator-v2-release.md
@@ -60,11 +60,11 @@ Now the documentation was split into the ["Guide"](../guide/overview) and ["Refe
We added 3 new pages with guides on how to use builders idiomatically or solve some common problems (e.g. validating inputs):
-- [Conditional Building](../guide/conditional-building)
-- [Fallible Builders](../guide/fallible-builders)
-- [Into Conversions In-Depth](../guide/into-conversions-in-depth)
+- [Conditional Building](../guide/patterns/conditional-building)
+- [Fallible Builders](../guide/patterns/fallible-builders)
+- [Into Conversions In-Depth](../guide/patterns/into-conversions-in-depth)
-I recommend you to check out the ["Into Conversions In-Depth"](../guide/into-conversions-in-depth) especially because it's highly related to one of the breaking changes that we'll review below.
+I recommend you to check out the ["Into Conversions In-Depth"](../guide/patterns/into-conversions-in-depth) especially because it's highly related to one of the breaking changes that we'll review below.
## Breaking changes
@@ -72,7 +72,7 @@ I recommend you to check out the ["Into Conversions In-Depth"](../guide/into-con
This has been a topic of [controversy](https://github.com/elastio/bon/issues/15), but finally, we aligned on the decision to remove the magical automatic `Into` conversions.
-The main reason for removing this is to make `bon` more obvious and intuitive. Rust's core pillar is "being explicit". By having automatic `Into` conversions `bon` v1 introduced magical implicit behaviour, that also could lead to some footguns. For a detailed explanation of the potential footguns, see the ["Into Conversions In-Depth"](../guide/into-conversions-in-depth) page.
+The main reason for removing this is to make `bon` more obvious and intuitive. Rust's core pillar is "being explicit". By having automatic `Into` conversions `bon` v1 introduced magical implicit behaviour, that also could lead to some footguns. For a detailed explanation of the potential footguns, see the ["Into Conversions In-Depth"](../guide/patterns/into-conversions-in-depth) page.
Now, if you want to enable `Into` conversions for a set of members, you can use the new [`#[builder(on(type_pattern, into))]`](../reference/builder/top-level/on) attribute. It allows you to specify the type that you want to enable `Into` conversions for explicitly.
diff --git a/website/src/blog/bon-builder-v2-2-release.md b/website/src/blog/bon-builder-v2-2-release.md
index 6efebb54..1712fd92 100644
--- a/website/src/blog/bon-builder-v2-2-release.md
+++ b/website/src/blog/bon-builder-v2-2-release.md
@@ -61,9 +61,9 @@ cargo fmt
A new attribute is now supported at the top level. You can add [`#[builder(derive(...))]`](../reference/builder/top-level/derive) to ask `bon` to generate implementations of `Clone` or `Debug` for the builder.
-This helps with reusing [partial builders](../guide/conditional-building#shared-partial-builder), because now you can clone the builder where only part of the fields are set.
+This helps with reusing [partial builders](../guide/patterns/conditional-building#shared-partial-builder), because now you can clone the builder where only part of the fields are set.
-The `Debug` derive allows you to [inspect](../guide/inspecting) the builder state for debugging purposes.
+The `Debug` derive allows you to [inspect](../guide/basics/inspecting) the builder state for debugging purposes.
**Example:**
diff --git a/website/src/blog/bon-builder-v2-3-release.md b/website/src/blog/bon-builder-v2-3-release.md
index f69c1a3c..9a889513 100644
--- a/website/src/blog/bon-builder-v2-3-release.md
+++ b/website/src/blog/bon-builder-v2-3-release.md
@@ -22,7 +22,7 @@ If you don't know about [`bon`], then see the [motivational blog post](./how-to-
### Positional arguments in starting and finishing functions
-While having the ability to use separate setters for the members gives you a ton of flexibility and extensibility described on the ["Compatibility"](../guide/compatibility) page, sometimes you don't need all of that.
+While having the ability to use separate setters for the members gives you a ton of flexibility and extensibility described on the ["Compatibility"](../guide/misc/compatibility) page, sometimes you don't need all of that.
Maybe you'd like to pick out some specific members and let the user pass their values as positional parameters to the starting function that creates the builder or to the finishing function that consumes it. This reduces the syntax a bit at the cost of some extensibility loss ⚖️, but it may be worth it!
@@ -32,8 +32,8 @@ As an example, suppose we have a `Treasure` struct with `x` and `y` coordinates
To do that we can use the `#[builder(start_fn)]` attribute. There are two contexts where we can place it, and they both have a different meaning:
-- [Top-level `#[builder(start_fn = ...)]`](../reference/builder/top-level/start-fn) - configures the name of the starting function and optionally its visibility
-- [Member-level `#[builder(start_fn)]`](../reference/builder/member/start-fn) - configures the member to be a positional parameter on the starting function
+- [Top-level `#[builder(start_fn = ...)]`](../reference/builder/top-level/start_fn) - configures the name of the starting function and optionally its visibility
+- [Member-level `#[builder(start_fn)]`](../reference/builder/member/start_fn) - configures the member to be a positional parameter on the starting function
We'll want to use both of these attributes in our example to give a better name for the starting function that describes its inputs and configure `x` and `y` as positional parameters on the starting function as well.
@@ -78,7 +78,7 @@ impl Treasure {
Now let's say we need to know the person who claimed the `Treasure`. While describing the treasure using the current builder syntax we'd like the person who claimed it to specify their first name and last name at the end of the building process.
-We can use a similar combination of the [top-level `#[builder(finish_fn = ...)]`](../reference/builder/top-level/finish-fn) and the [member-level `#[builder(finish_fn)]`](../reference/builder/member/finish-fn) attributes to do that.
+We can use a similar combination of the [top-level `#[builder(finish_fn = ...)]`](../reference/builder/top-level/finish_fn) and the [member-level `#[builder(finish_fn)]`](../reference/builder/member/finish_fn) attributes to do that.
**Example:**
@@ -115,7 +115,7 @@ assert_eq!(treasure.claimed_by_first_name, "Lyra"); // [!code highlight]
assert_eq!(treasure.claimed_by_last_name, "Heartstrings"); // [!code highlight]
```
-You may also combine these attributes with [`#[builder(into)]`](../reference/builder/member/into) or [`#[builder(on(..., into))]`](../reference/builder/top-level/on) to reduce the number of `to_owned()` calls a bit. See this described in detail on the new ["Positional members"](../guide/positional-members#into-conversions) page in the guide.
+The new [Positional Members](../guide/basics/positional-members) page was added to the guide.
### Guaranteed MSRV is 1.59.0 now
diff --git a/website/src/blog/how-to-do-named-function-arguments-in-rust.md b/website/src/blog/how-to-do-named-function-arguments-in-rust.md
index a9a597dc..0a02afa0 100644
--- a/website/src/blog/how-to-do-named-function-arguments-in-rust.md
+++ b/website/src/blog/how-to-do-named-function-arguments-in-rust.md
@@ -146,7 +146,7 @@ User::builder()
.build();
```
-So, you can use just one builder crate solution consistently for everything. Builders for functions and structs both share the same API design, which allows you, for example, to switch between a `#[derive(Builder)]` on a struct and a `#[builder]` attribute on a method that creates a struct. This won't be an API-breaking change for your consumers ([details](../guide/compatibility#switching-between-derive-builder-and-builder-on-the-new-method)).
+So, you can use just one builder crate solution consistently for everything. Builders for functions and structs both share the same API design, which allows you, for example, to switch between a `#[derive(Builder)]` on a struct and a `#[builder]` attribute on a method that creates a struct. This won't be an API-breaking change for your consumers ([details](../guide/misc/compatibility#switching-between-derive-builder-and-builder-on-the-new-method)).
## Summary
diff --git a/website/src/changelog.md b/website/src/changelog.md
index ddc0e7a0..d15651e6 100644
--- a/website/src/changelog.md
+++ b/website/src/changelog.md
@@ -49,7 +49,7 @@ All the breaking changes are very unlikely to actually break your code that was
- ⚠️ **Breaking.** Builder macros now generate additional `mod builder_name {}` where `builder_name` is the snake_case version of the name of the builder struct. This new module contains the type state API of the builder. There is a low probability that this new module name may conflict with existing symbols in your scope, so this change is marked as breaking.
-- Add [`#[builder(builder_type(vis = "...", doc { ... }))]`](https://bon-rs.com/reference/builder/top-level/builder-type) that allows overriding the visibility and docs of the builder struct ([#145](https://github.com/elastio/bon/pull/145))
+- Add [`#[builder(builder_type(vis = "...", doc { ... }))]`](https://bon-rs.com/reference/builder/top-level/builder_type) that allows overriding the visibility and docs of the builder struct ([#145](https://github.com/elastio/bon/pull/145))
- Add [`#[builder(finish_fn(vis = "...", doc { ... } ))]`](https://bon-rs.com/reference/builder/top-level/finish-fn) that allows overriding the visibility and docs of the finishing function ([#145](https://github.com/elastio/bon/pull/145))
diff --git a/website/src/guide/basics/custom-conversions.md b/website/src/guide/basics/custom-conversions.md
index 84696a33..68e0e8b9 100644
--- a/website/src/guide/basics/custom-conversions.md
+++ b/website/src/guide/basics/custom-conversions.md
@@ -28,4 +28,4 @@ assert_eq!(value.point.y, 3);
You can also pass a [fallible closure](../../reference/builder/member/with#fallible-setters) and some [well-known functions](../../reference/builder/member/with#well-known-functions) to `#[builder(with)]`.
-If your setter needs more complex logic that isn't expressible with `#[builder(with)]` (e.g. mark the setter `unsafe`, set several members at once), then [Custom Methods](./custom-methods) can cover that.
+If your setter needs more complex logic that isn't expressible with `#[builder(with)]` (e.g. mark the setter `unsafe`, set several members at once), then [Custom Methods](../typestate-api/custom-methods) can cover that.
diff --git a/website/src/guide/basics/inspecting.md b/website/src/guide/basics/inspecting.md
index 1872c70b..938a93ec 100644
--- a/website/src/guide/basics/inspecting.md
+++ b/website/src/guide/basics/inspecting.md
@@ -1,6 +1,6 @@
# Inspecting
-If you want to inspect the values set in the builder for debugging purposes you can leverage the [`#[builder(derive(...))]`](../reference/builder/top-level/derive) attribute to derive the [`Debug`](https://doc.rust-lang.org/stable/std/fmt/trait.Debug.html) trait for your builder.
+If you want to inspect the values set in the builder for debugging purposes you can leverage the [`#[builder(derive(...))]`](../../reference/builder/top-level/derive) attribute to derive the [`Debug`](https://doc.rust-lang.org/stable/std/fmt/trait.Debug.html) trait for your builder.
**Example:**
@@ -30,4 +30,4 @@ assert_eq!(
builder.is_admin(true).call();
```
-You can also derive the [`Clone`](https://doc.rust-lang.org/stable/std/clone/trait.Clone.html) trait for your builder using this same attribute. See more details in the [reference for the `#[builder(derive(...))]` attribute](../reference/builder/top-level/derive).
+You can also derive the [`Clone`](https://doc.rust-lang.org/stable/std/clone/trait.Clone.html) trait for your builder using this same attribute. See more details in the [reference for the `#[builder(derive(...))]` attribute](../../reference/builder/top-level/derive).
diff --git a/website/src/guide/basics/into-conversions.md b/website/src/guide/basics/into-conversions.md
index 09c22047..e56330af 100644
--- a/website/src/guide/basics/into-conversions.md
+++ b/website/src/guide/basics/into-conversions.md
@@ -22,7 +22,7 @@ Project::builder()
However, you can ask `bon` to generate setters that accept `impl Into` to remove the need for manual conversion.
-This can be configured with [`#[builder(into)]`](../reference/builder/member/into) for a single member or with [`#[builder(on({type}, into))]`](../reference/builder/top-level/on) for many members at once.
+This can be configured with [`#[builder(into)]`](../../reference/builder/member/into) for a single member or with [`#[builder(on({type}, into))]`](../../reference/builder/top-level/on) for many members at once.
```rust
use bon::Builder;
diff --git a/website/src/guide/basics/optional-members.md b/website/src/guide/basics/optional-members.md
index 1e6324c4..2ba1556a 100644
--- a/website/src/guide/basics/optional-members.md
+++ b/website/src/guide/basics/optional-members.md
@@ -16,7 +16,7 @@ fn example(level: Option) {}
example().call();
```
-You can use [`#[builder(transparent)]`](../reference/builder/member/transparent) to opt-out from this.
+You can use [`#[builder(transparent)]`](../../reference/builder/member/transparent) to opt-out from this.
### Setters pair
@@ -27,7 +27,7 @@ The builder provides a **pair** of setters for each optional member:
| `{member}` | `T` | Accepts a non-`None` value. | [`some_fn`][setters]
| `maybe_{member}` | `Option` | Accepts an `Option` directly. | [`option_fn`][setters]
-[setters]: ../reference/builder/member/setters
+[setters]: ../../reference/builder/member/setters
::: details See how the setters look in the generated code
@@ -45,7 +45,7 @@ impl ExampleBuilder {
:::
-Thanks to this design, changing the member from required to optional [preserves compatibility](./compatibility#making-a-required-member-optional).
+Thanks to this design, changing the member from required to optional [preserves compatibility](../misc/compatibility#making-a-required-member-optional).
### Examples
@@ -69,11 +69,11 @@ example().maybe_level(value).call();
## `#[builder(default)]`
-To make a member of non-`Option` type optional you may use [`#[builder(default)]`](../reference/builder/member/default). This attribute uses the [`Default`](https://doc.rust-lang.org/stable/std/default/trait.Default.html) trait or the provided expression to assign the default value for the member.
+To make a member of non-`Option` type optional you may use [`#[builder(default)]`](../../reference/builder/member/default). This attribute uses the [`Default`](https://doc.rust-lang.org/stable/std/default/trait.Default.html) trait or the provided expression to assign the default value for the member.
::: tip
-Switching between `#[builder(default)]` and `Option` is [compatible](./compatibility#switching-between-option-t-and-builder-default).
+Switching between `#[builder(default)]` and `Option` is [compatible](../misc/compatibility#switching-between-option-t-and-builder-default).
:::
diff --git a/website/src/guide/misc/alternatives.md b/website/src/guide/misc/alternatives.md
index a48e6df1..44f1ba13 100644
--- a/website/src/guide/misc/alternatives.md
+++ b/website/src/guide/misc/alternatives.md
@@ -53,7 +53,7 @@ fn main() {
::: tip
-Why is there an explicit `main()` function in this code snippet 🤔? It's a long story explained in a [blog post](../blog/the-weird-of-function-local-types-in-rust) (feel free to skip).
+Why is there an explicit `main()` function in this code snippet 🤔? It's a long story explained in a [blog post](/blog/the-weird-of-function-local-types-in-rust) (feel free to skip).
:::
@@ -98,8 +98,8 @@ Another difference is that fields of collection types are considered required by
[map]: https://docs.rs/bon/latest/bon/macro.map.html
[set]: https://docs.rs/bon/latest/bon/macro.set.html
[mutators]: https://docs.rs/typed-builder/latest/typed_builder/derive.TypedBuilder.html#mutators
-[bon-on]: ../reference/builder/top-level/on
-[bon-into]: ../reference/builder/member/into
+[bon-on]: ../../reference/builder/top-level/on
+[bon-into]: ../../reference/builder/member/into
[bs-into]: https://docs.rs/buildstructor/latest/buildstructor/#into-field
[db-into]: https://docs.rs/derive_builder/latest/derive_builder/#generic-setters
[r1]: #special-setter-methods-for-collections
diff --git a/website/src/guide/misc/compatibility.md b/website/src/guide/misc/compatibility.md
index 6f47b26a..5b23793c 100644
--- a/website/src/guide/misc/compatibility.md
+++ b/website/src/guide/misc/compatibility.md
@@ -2,7 +2,7 @@
## Making a required member optional
-It's totally backwards compatible to make a required member optional by changing the type from `T` to `Option` or by adding [`#[builder(default)]`](../reference/builder/member/default) to it.
+It's totally backwards compatible to make a required member optional by changing the type from `T` to `Option` or by adding [`#[builder(default)]`](../../reference/builder/member/default) to it.
This is because both required and optional members have a setter that accepts `T` (not wrapped in an `Option`). The only change to the public API when making the required member optional is that a `maybe_`-prefixed setter is added to the builder. That new method accepts an `Option`.
@@ -179,4 +179,4 @@ let user = User::builder()
Let's suppose you have existing code that defines functions with positional parameters in the public API. You'd like to change it to expose builder syntax instead, but you want to keep the old code compatible with the positional functions API.
-In this case, you may use the top-level attribute `#[builder(start_fn)]` to keep both syntaxes available. See examples in the [docs for this attribute](../reference/builder/top-level/start-fn#exposing-original-function).
+In this case, you may use the top-level attribute `#[builder(start_fn)]` to keep both syntaxes available. See examples in the [docs for this attribute](../../reference/builder/top-level/start_fn#exposing-original-function).
diff --git a/website/src/guide/patterns/conditional-building.md b/website/src/guide/patterns/conditional-building.md
index 22fb9952..7373f4ad 100644
--- a/website/src/guide/patterns/conditional-building.md
+++ b/website/src/guide/patterns/conditional-building.md
@@ -104,7 +104,7 @@ let user = User::builder()
.build();
```
-In this case, we create a variable for each conditional member beforehand and initialize them separately, then we pass the results to the builder. We benefit from the `maybe_` setters for [optional members](./optional-members) such that we can pass the `Option` values directly.
+In this case, we create a variable for each conditional member beforehand and initialize them separately, then we pass the results to the builder. We benefit from the `maybe_` setters for [optional members](../basics/optional-members) such that we can pass the `Option` values directly.
::: tip NOTE
diff --git a/website/src/guide/patterns/into-conversions-in-depth.md b/website/src/guide/patterns/into-conversions-in-depth.md
index f5168e14..003b73f7 100644
--- a/website/src/guide/patterns/into-conversions-in-depth.md
+++ b/website/src/guide/patterns/into-conversions-in-depth.md
@@ -7,7 +7,7 @@ outline: deep
## Preface
-This is the continuation of the ["Into conversions" section](./overview#into-conversions) from the general overview page. This page describes the important caveats of using `impl Into` that you should know before enabling them.
+This is the continuation of [Into Conversions](../basics/into-conversions) from the `Basics` section. This page describes important caveats of using `impl Into` that you should know before enabling them.
Make sure you are familiar with the standard [`From`](https://doc.rust-lang.org/stable/std/convert/trait.From.html) and [`Into`](https://doc.rust-lang.org/stable/std/convert/trait.Into.html) traits before you proceed. Reading their docs is pretty much enough. For example, you should know that every type that implements `From` automatically implements `Into`. Also, you should know that you can pass a value of type `T` at no cost directly to a function that accepts `impl Into` thanks to [this blanket](https://github.com/rust-lang/rust/blob/1a94d839be8b248b972b9e022cb940d56de72fa1/library/core/src/convert/mod.rs#L763-L771) impl in `std`.
diff --git a/website/src/guide/patterns/shared-configuration.md b/website/src/guide/patterns/shared-configuration.md
index 349a3cee..cd59b58b 100644
--- a/website/src/guide/patterns/shared-configuration.md
+++ b/website/src/guide/patterns/shared-configuration.md
@@ -8,7 +8,7 @@ On this page, you'll learn how to share common configurations for builders to av
## Problem statement
-As an example, let's suppose you want to enable [`Into` conversions](./into-conversions-in-depth) for specific types across all your builders and maybe also override the name of the finishing function that consumes the builder from the default `build` to `finish`.
+As an example, let's suppose you want to enable [`Into` conversions](../patterns/into-conversions-in-depth) for specific types across all your builders and maybe also override the name of the finishing function that consumes the builder from the default `build` to `finish`.
You'll quickly run into a problem, where you need to repeat the same configuration for every usage of the builder macro.
@@ -35,7 +35,7 @@ struct MyLovelyStruct2 { /**/ }
::: tip
-This code uses the [`#[builder(on(...))]`](../reference/builder/top-level/on) attribute to configure the types of members for which `bon` should enable `Into` conversions.
+This code uses the [`#[builder(on(...))]`](../../reference/builder/top-level/on) attribute to configure the types of members for which `bon` should enable `Into` conversions.
:::
diff --git a/website/src/guide/typestate-api.md b/website/src/guide/typestate-api.md
index 11f6730d..8dc2dfc1 100644
--- a/website/src/guide/typestate-api.md
+++ b/website/src/guide/typestate-api.md
@@ -2,6 +2,6 @@
This section teaches you the builder's typestate API. It describes the underlying component traits and types of the builder type and how to use them.
-Reading this is optional. The typestate API is private by default. The users of your builder can't denote its type unless you enable [`#[builder(state_mod(vis = "pub"))]`](../../reference/builder/top-level/state_mod).
+Reading this is optional. The typestate API is private by default. The users of your builder can't denote its type unless you enable [`#[builder(state_mod(vis = "pub"))]`](../reference/builder/top-level/state_mod).
It is more of an advanced concept that you'll rarely need. However, "advanced" doesn't necessarily mean "complicated" in this case. So feel free to study this section if you feel like it.
diff --git a/website/src/reference/builder.md b/website/src/reference/builder.md
index c0627d02..48a5b1b6 100644
--- a/website/src/reference/builder.md
+++ b/website/src/reference/builder.md
@@ -12,12 +12,12 @@ These attributes are placed on top of a `struct` or `fn` declaration.
| Attribute | Short description
| -- | -- |
-| [`builder_type`](./builder/top-level/builder-type) | Overrides name, visibility and docs for the builder struct
+| [`builder_type`](./builder/top-level/builder_type) | Overrides name, visibility and docs for the builder struct
| [`crate`](./builder/top-level/crate) | Overrides path to `bon` crate referenced in the generated code
| [`derive`](./builder/top-level/derive) | Generates additional derives for the builder struct itself
-| [`finish_fn`](./builder/top-level/finish-fn) | Overrides name, visibility and docs for the finishing function
+| [`finish_fn`](./builder/top-level/finish_fn) | Overrides name, visibility and docs for the finishing function
| [`on`](./builder/top-level/on) | Applies member attributes to all members matching a type pattern
-| [`start_fn`](./builder/top-level/start-fn) | Overrides name, visibility and docs for the starting function
+| [`start_fn`](./builder/top-level/start_fn) | Overrides name, visibility and docs for the starting function
## Member Attributes
@@ -26,13 +26,13 @@ These attributes are placed on a `struct` field or `fn` argument.
| Attribute | Short description
| -- | -- |
| [`default`](./builder/member/default) | Makes the member optional with a default value
-| [`finish_fn`](./builder/member/finish-fn) | Makes the member a positional argument on the finishing function
+| [`finish_fn`](./builder/member/finish_fn) | Makes the member a positional argument on the finishing function
| [`into`](./builder/member/into) | Changes the signature of the setters to accept `impl Into`
| [`name`](./builder/member/name) | Overrides the name of the member used in the builder's API
| [`overwritable` 🔬](./builder/member/overwritable) | Allows calling setters for the same member repeatedly
| [`setters`](./builder/member/setters) | Overrides name, visibility and docs for setters
| [`skip`](./builder/member/skip) | Skips generating setters for the member
-| [`start_fn`](./builder/member/start-fn) | Makes the member a positional argument on the starting function
+| [`start_fn`](./builder/member/start_fn) | Makes the member a positional argument on the starting function
| [`transparent`](./builder/member/transparent) | Disables `Option` special handling, makes the member required
| [`with`](./builder/member/with) | ??????? TODO: ADD DOCS ??????
diff --git a/website/src/reference/builder/member/default.md b/website/src/reference/builder/member/default.md
index a7d7887b..a7d256e1 100644
--- a/website/src/reference/builder/member/default.md
+++ b/website/src/reference/builder/member/default.md
@@ -15,7 +15,7 @@ If combined with [`#[builder(into)]`](./into), the default expression is additio
## Setters
-Two setter methods are generated for the member with `#[builder(default)]` just like for [members of type `Option`](../../../guide/optional-members#setters-pair):
+Two setter methods are generated for the member with `#[builder(default)]` just like for [members of type `Option`](../../../guide/basics/optional-members#setters-pair):
| Name | Input | Description | Configuration attribute
|------------------|-------------|-------------------------------|------------------
@@ -26,7 +26,7 @@ If `None` is passed to the `maybe_{member}` setter, then the default value is us
::: tip
-Switching between `#[builder(default)]` and `Option` is [compatible](../../../guide/compatibility#switching-between-option-t-and-builder-default).
+Switching between `#[builder(default)]` and `Option` is [compatible](../../../guide/misc/compatibility#switching-between-option-t-and-builder-default).
:::
diff --git a/website/src/reference/builder/member/into.md b/website/src/reference/builder/member/into.md
index 5e89fa25..56ac8beb 100644
--- a/website/src/reference/builder/member/into.md
+++ b/website/src/reference/builder/member/into.md
@@ -10,13 +10,13 @@ This attribute is also configurable via the top-level [`#[builder(on(...))]`](..
Changes the signature of the setters to accept [`impl Into`](https://doc.rust-lang.org/stable/std/convert/trait.Into.html), where `T` is the type of the member.
-For [optional members](../../../guide/optional-members), the `maybe_{member}()` setter method will accept an `Option>` type instead of just `Option`.
+For [optional members](../../../guide/basics/optional-members), the `maybe_{member}()` setter method will accept an `Option>` type instead of just `Option`.
For members that use `#[builder(default = expression)]`, the `expression` will be converted with `Into::into`.
This parameter is often used with the `String` type, which allows you to pass `&str` into the setter without calling `.to_owned()` or `.to_string()` on it.
-See the ["Into Conversions In-Depth"](../../../guide/into-conversions-in-depth) page that shows the common patterns and antipatterns of `impl Into`.
+See the [Into Conversions In-Depth](../../../guide/patterns/into-conversions-in-depth) page that shows the common patterns and antipatterns of `impl Into`.
## Examples
diff --git a/website/src/reference/builder/member/overwritable.md b/website/src/reference/builder/member/overwritable.md
index 10de2795..d2d17269 100644
--- a/website/src/reference/builder/member/overwritable.md
+++ b/website/src/reference/builder/member/overwritable.md
@@ -38,7 +38,7 @@ Overwrites like in the example above are generally considered bugs. However, the
## Improving compile times
-This attribute simplifies the generated code. For example, it completely removes type states for [optional members](../../../guide/optional-members).
+This attribute simplifies the generated code. For example, it completely removes type states for [optional members](../../../guide/basics/optional-members).
If you'd like to improve your compile times, consider enabling overwrites with `#[builder(on(_, overwritable))]` and checking how much it helps. The difference is visible on a larger scale, especially for structs/functions with tens of optional members.
@@ -48,11 +48,9 @@ It is a trade-off between the level of compile-time checks and compilation perfo
You might want to use this to construct dummy values for tests (fixtures).
-**Example:**
-
::: tip
-The builder's type signature mentioned in this example is described in the ["Builder Extensions"](../../../guide/builder-extensions) guide.
+The builder's type signature mentioned in this example is described in the [Builder's Type Signature](../../../guide/typestate-api/builders-type-signature) guide.
:::
diff --git a/website/src/reference/builder/member/setters.md b/website/src/reference/builder/member/setters.md
index 541361c7..cfdd1279 100644
--- a/website/src/reference/builder/member/setters.md
+++ b/website/src/reference/builder/member/setters.md
@@ -38,11 +38,11 @@ The config is tree-structured with overrides precedence explained in the next pa
)]
```
-The main use case for this attribute is making generated setters private to wrap them with custom setters. See ["Builder extensions"](../../../guide/builder-extensions#custom-setters) for details.
+The main use case for this attribute is making generated setters private to wrap them with custom methods. See [Custom Methods](../../../guide/typestate-api/custom-methods) for details.
## Config precedence
-The keys `some_fn` and `option_fn` are available only for optional members that have a [pair of setters](../../../guide/optional-members#setters-pair).
+The keys `some_fn` and `option_fn` are available only for optional members that have a [pair of setters](../../../guide/basics/optional-members#setters-pair).
The root-level `name`, `vis`, `docs` are still available for both required and optional setters. They can be overwritten at `some_fn` and `option_fn` level individually.
@@ -77,7 +77,7 @@ This attribute is different from [`#[builder(name)]`](./name), because it overri
The visibility must be enclosed with quotes. Use `""` or [`"pub(self)"`](https://doc.rust-lang.org/reference/visibility-and-privacy.html#pubin-path-pubcrate-pubsuper-and-pubself) for private visibility.
-The default visibility is the same as the visibility of the [`builder_type`](../top-level/builder-type#vis), which in turn, defaults to the visibility of the underlying `struct` or `fn`.
+The default visibility is the same as the visibility of the [`builder_type`](../top-level/builder_type#vis), which in turn, defaults to the visibility of the underlying `struct` or `fn`.
## `doc`
diff --git a/website/src/reference/builder/member/start_fn.md b/website/src/reference/builder/member/start_fn.md
index e61e5230..e9af3463 100644
--- a/website/src/reference/builder/member/start_fn.md
+++ b/website/src/reference/builder/member/start_fn.md
@@ -92,7 +92,7 @@ assert_eq!(value.2, 3);
:::
-You can rename the starting function from default `builder()` for structs to something more readable via the top-level [`#[builder(start_fn = ...)]`](../top-level/start-fn) attribute.
+You can rename the starting function from default `builder()` for structs to something more readable via the top-level [`#[builder(start_fn = ...)]`](../top-level/start_fn) attribute.
## Ordering
diff --git a/website/src/reference/builder/member/with.md b/website/src/reference/builder/member/with.md
index 3481cd3e..545df081 100644
--- a/website/src/reference/builder/member/with.md
+++ b/website/src/reference/builder/member/with.md
@@ -9,7 +9,7 @@ If the closure accepts a single parameter `T`, then the `maybe_` setter accepts
You can use `impl Trait` for parameters in the closure, even though you can't in the usual Rust code.
-There are several well-known functions that you can use instead of the closure syntax to shorten your code e.g. `#[builder(with = Some)]` and `#[builder(with = FromIterator::from_iter)]` (more details [here](../../reference/builder/member/with#well-known-functions)).
+
## Optional members
diff --git a/website/src/reference/builder/top-level/finish_fn.md b/website/src/reference/builder/top-level/finish_fn.md
index 8b3b97cb..dc57ee0b 100644
--- a/website/src/reference/builder/top-level/finish_fn.md
+++ b/website/src/reference/builder/top-level/finish_fn.md
@@ -45,7 +45,7 @@ The default name for the finishing function is chosen according to the following
The visibility must be enclosed with quotes. Use `""` or [`"pub(self)"`](https://doc.rust-lang.org/reference/visibility-and-privacy.html#pubin-path-pubcrate-pubsuper-and-pubself) for private visibility.
-The default visibility is the same as the visibility of the [`builder_type`](./builder-type#vis), which in turn, defaults to the visibility of the underlying `struct` or `fn`.
+The default visibility is the same as the visibility of the [`builder_type`](./builder_type#vis), which in turn, defaults to the visibility of the underlying `struct` or `fn`.
## `doc`
diff --git a/website/src/reference/builder/top-level/start_fn.md b/website/src/reference/builder/top-level/start_fn.md
index 9955ea37..2cbf9b21 100644
--- a/website/src/reference/builder/top-level/start_fn.md
+++ b/website/src/reference/builder/top-level/start_fn.md
@@ -47,7 +47,7 @@ The default name for the starting function is chosen according to the following
The visibility must be enclosed with quotes. Use `""` or [`"pub(self)"`](https://doc.rust-lang.org/reference/visibility-and-privacy.html#pubin-path-pubcrate-pubsuper-and-pubself) for private visibility.
-The default visibility is the same as the visibility of the [`builder_type`](./builder-type#vis), which in turn, defaults to the visibility of the underlying `struct` or `fn`.
+The default visibility is the same as the visibility of the [`builder_type`](./builder_type#vis), which in turn, defaults to the visibility of the underlying `struct` or `fn`.
## `doc`
diff --git a/website/src/reference/builder/top-level/state_mod.md b/website/src/reference/builder/top-level/state_mod.md
index 8490ab72..c3b15e19 100644
--- a/website/src/reference/builder/top-level/state_mod.md
+++ b/website/src/reference/builder/top-level/state_mod.md
@@ -1,3 +1,5 @@
# `state_mod`
TODO: add docs
+
+## `doc`