bon-3.7.1/.cargo_vcs_info.json 0000644 00000000141 00000000001 0011616 0 ustar {
"git": {
"sha1": "bc940a1209420d3a613f8ea4ecf1992d984b9951"
},
"path_in_vcs": "bon"
} bon-3.7.1/Cargo.lock 0000644 00000035343 00000000001 0007605 0 ustar # This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "addr2line"
version = "0.24.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1"
dependencies = [
"gimli",
]
[[package]]
name = "adler2"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
[[package]]
name = "backtrace"
version = "0.3.75"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002"
dependencies = [
"addr2line",
"cfg-if",
"libc",
"miniz_oxide",
"object",
"rustc-demangle",
"windows-targets",
]
[[package]]
name = "bitflags"
version = "2.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967"
[[package]]
name = "bon"
version = "3.7.1"
dependencies = [
"bon-macros",
"expect-test",
"macro_rules_attribute",
"rustversion",
"tokio",
"trybuild",
]
[[package]]
name = "bon-macros"
version = "3.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca5abbf2d4a4c6896197c9de13d6d7cb7eff438c63dacde1dde980569cb00248"
dependencies = [
"darling",
"ident_case",
"prettyplease",
"proc-macro2",
"quote",
"rustversion",
"syn",
]
[[package]]
name = "cfg-if"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268"
[[package]]
name = "darling"
version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a79c4acb1fd5fa3d9304be4c76e031c54d2e92d172a393e24b19a14fe8532fe9"
dependencies = [
"darling_core",
"darling_macro",
]
[[package]]
name = "darling_core"
version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74875de90daf30eb59609910b84d4d368103aaec4c924824c6799b28f77d6a1d"
dependencies = [
"fnv",
"ident_case",
"proc-macro2",
"quote",
"strsim",
"syn",
]
[[package]]
name = "darling_macro"
version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e79f8e61677d5df9167cd85265f8e5f64b215cdea3fb55eebc3e622e44c7a146"
dependencies = [
"darling_core",
"quote",
"syn",
]
[[package]]
name = "dissimilar"
version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8975ffdaa0ef3661bfe02dbdcc06c9f829dfafe6a3c474de366a8d5e44276921"
[[package]]
name = "equivalent"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
[[package]]
name = "expect-test"
version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "63af43ff4431e848fb47472a920f14fa71c24de13255a5692e93d4e90302acb0"
dependencies = [
"dissimilar",
"once_cell",
]
[[package]]
name = "fnv"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "gimli"
version = "0.31.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
[[package]]
name = "glob"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2"
[[package]]
name = "hashbrown"
version = "0.15.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5"
[[package]]
name = "ident_case"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]]
name = "indexmap"
version = "2.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661"
dependencies = [
"equivalent",
"hashbrown",
]
[[package]]
name = "io-uring"
version = "0.7.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b86e202f00093dcba4275d4636b93ef9dd75d025ae560d2521b45ea28ab49013"
dependencies = [
"bitflags",
"cfg-if",
"libc",
]
[[package]]
name = "itoa"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
[[package]]
name = "libc"
version = "0.2.174"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776"
[[package]]
name = "macro_rules_attribute"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "65049d7923698040cd0b1ddcced9b0eb14dd22c5f86ae59c3740eab64a676520"
dependencies = [
"macro_rules_attribute-proc_macro",
"paste",
]
[[package]]
name = "macro_rules_attribute-proc_macro"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "670fdfda89751bc4a84ac13eaa63e205cf0fd22b4c9a5fbfa085b63c1f1d3a30"
[[package]]
name = "memchr"
version = "2.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0"
[[package]]
name = "miniz_oxide"
version = "0.8.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316"
dependencies = [
"adler2",
]
[[package]]
name = "mio"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c"
dependencies = [
"libc",
"wasi",
"windows-sys",
]
[[package]]
name = "object"
version = "0.36.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87"
dependencies = [
"memchr",
]
[[package]]
name = "once_cell"
version = "1.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
[[package]]
name = "paste"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
[[package]]
name = "pin-project-lite"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
[[package]]
name = "prettyplease"
version = "0.2.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "061c1221631e079b26479d25bbf2275bfe5917ae8419cd7e34f13bfc2aa7539a"
dependencies = [
"proc-macro2",
"syn",
]
[[package]]
name = "proc-macro2"
version = "1.0.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rustc-demangle"
version = "0.1.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "989e6739f80c4ad5b13e0fd7fe89531180375b18520cc8c82080e4dc4035b84f"
[[package]]
name = "rustversion"
version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d"
[[package]]
name = "ryu"
version = "1.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
[[package]]
name = "serde"
version = "1.0.219"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.219"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.140"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373"
dependencies = [
"itoa",
"memchr",
"ryu",
"serde",
]
[[package]]
name = "serde_spanned"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "40734c41988f7306bb04f0ecf60ec0f3f1caa34290e4e8ea471dcd3346483b83"
dependencies = [
"serde",
]
[[package]]
name = "slab"
version = "0.4.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04dc19736151f35336d325007ac991178d504a119863a2fcb3758cdb5e52c50d"
[[package]]
name = "strsim"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]]
name = "syn"
version = "2.0.104"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "target-triple"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ac9aa371f599d22256307c24a9d748c041e548cbf599f35d890f9d365361790"
[[package]]
name = "termcolor"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755"
dependencies = [
"winapi-util",
]
[[package]]
name = "tokio"
version = "1.47.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038"
dependencies = [
"backtrace",
"io-uring",
"libc",
"mio",
"pin-project-lite",
"slab",
"tokio-macros",
]
[[package]]
name = "tokio-macros"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "toml"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed0aee96c12fa71097902e0bb061a5e1ebd766a6636bb605ba401c45c1650eac"
dependencies = [
"indexmap",
"serde",
"serde_spanned",
"toml_datetime",
"toml_parser",
"toml_writer",
"winnow",
]
[[package]]
name = "toml_datetime"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bade1c3e902f58d73d3f294cd7f20391c1cb2fbcb643b73566bc773971df91e3"
dependencies = [
"serde",
]
[[package]]
name = "toml_parser"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97200572db069e74c512a14117b296ba0a80a30123fbbb5aa1f4a348f639ca30"
dependencies = [
"winnow",
]
[[package]]
name = "toml_writer"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fcc842091f2def52017664b53082ecbbeb5c7731092bad69d2c63050401dfd64"
[[package]]
name = "trybuild"
version = "1.0.106"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "65af40ad689f2527aebbd37a0a816aea88ff5f774ceabe99de5be02f2f91dae2"
dependencies = [
"glob",
"serde",
"serde_derive",
"serde_json",
"target-triple",
"termcolor",
"toml",
]
[[package]]
name = "unicode-ident"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
[[package]]
name = "wasi"
version = "0.11.1+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
[[package]]
name = "winapi-util"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
dependencies = [
"windows-sys",
]
[[package]]
name = "windows-sys"
version = "0.59.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_gnullvm",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]]
name = "windows_i686_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]]
name = "windows_i686_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]]
name = "winnow"
version = "0.7.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3edebf492c8125044983378ecb5766203ad3b4c2f7a922bd7dd207f6d443e95"
bon-3.7.1/Cargo.toml 0000644 00000013752 00000000001 0007630 0 ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
#
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
# to registry (e.g., crates.io) dependencies.
#
# If you are reading this file be aware that the original Cargo.toml
# will likely look very different (and much more reasonable).
# See Cargo.toml.orig for the original contents.
[package]
edition = "2021"
rust-version = "1.59.0"
name = "bon"
version = "3.7.1"
build = false
autolib = false
autobins = false
autoexamples = false
autotests = false
autobenches = false
description = "Next-gen compile-time-checked builder generator, named function's arguments, and more!"
homepage = "https://bon-rs.com"
readme = "README.md"
keywords = [
"builder",
"macro",
"derive",
"constructor",
"setter",
]
categories = [
"rust-patterns",
"data-structures",
"asynchronous",
"no-std",
"no-std::no-alloc",
]
license = "MIT OR Apache-2.0"
repository = "https://github.com/elastio/bon"
[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--generate-link-to-definition"]
targets = ["x86_64-unknown-linux-gnu"]
[features]
alloc = ["bon-macros/alloc"]
default = ["std"]
experimental-getter = []
experimental-overwritable = ["bon-macros/experimental-overwritable"]
implied-bounds = ["bon-macros/implied-bounds"]
std = [
"bon-macros/std",
"alloc",
]
[lib]
name = "bon"
path = "src/lib.rs"
[[test]]
name = "integration"
path = "tests/integration/main.rs"
[dependencies.bon-macros]
version = "=3.7.1"
[dependencies.rustversion]
version = "1"
[dev-dependencies.expect-test]
version = "1.4.1"
[dev-dependencies.macro_rules_attribute]
version = "0.2"
[dev-dependencies.tokio]
version = "1.29.1"
features = [
"macros",
"rt",
]
[dev-dependencies.trybuild]
version = "1.0.89"
[lints.clippy]
assertions_on_result_states = "warn"
await_holding_refcell_ref = "warn"
bool_to_int_with_if = "warn"
borrow_as_ptr = "warn"
branches_sharing_code = "warn"
cast_lossless = "warn"
cast_ptr_alignment = "warn"
checked_conversions = "warn"
clear_with_drain = "warn"
cloned_instead_of_copied = "warn"
collection_is_never_read = "warn"
copy_iterator = "warn"
dbg_macro = "warn"
debug_assert_with_mut_call = "warn"
default_union_representation = "warn"
doc_link_with_quotes = "warn"
doc_markdown = "warn"
empty_drop = "warn"
empty_line_after_doc_comments = "warn"
empty_line_after_outer_attr = "warn"
expl_impl_clone_on_copy = "warn"
explicit_into_iter_loop = "warn"
explicit_iter_loop = "warn"
filter_map_next = "warn"
flat_map_option = "warn"
float_cmp = "warn"
fn_params_excessive_bools = "warn"
fn_to_numeric_cast_any = "warn"
format_push_string = "warn"
if_then_some_else_none = "warn"
implicit_clone = "warn"
implicit_saturating_sub = "warn"
imprecise_flops = "warn"
index_refutable_slice = "warn"
indexing_slicing = "warn"
invalid_upcast_comparisons = "warn"
iter_not_returning_iterator = "warn"
iter_on_empty_collections = "warn"
iter_with_drain = "warn"
large_include_file = "warn"
linkedlist = "warn"
lossy_float_literal = "warn"
manual_clamp = "warn"
manual_instant_elapsed = "warn"
manual_let_else = "allow"
manual_ok_or = "warn"
many_single_char_names = "warn"
map_flatten = "warn"
map_unwrap_or = "allow"
match_wild_err_arm = "warn"
maybe_infinite_iter = "warn"
mixed_read_write_in_expression = "warn"
mut_mut = "warn"
naive_bytecount = "warn"
needless_bitwise_bool = "warn"
needless_collect = "warn"
needless_continue = "warn"
needless_for_each = "warn"
negative_feature_names = "warn"
no_effect_underscore_binding = "warn"
no_mangle_with_rust_abi = "warn"
non_send_fields_in_send_ty = "warn"
nonstandard_macro_braces = "warn"
or_fun_call = "warn"
path_buf_push_overwrite = "warn"
ptr_as_ptr = "warn"
range_minus_one = "warn"
range_plus_one = "warn"
rc_buffer = "warn"
rc_mutex = "warn"
read_zero_byte_vec = "warn"
redundant_clone = "warn"
redundant_feature_names = "warn"
ref_binding_to_reference = "warn"
ref_option_ref = "warn"
rest_pat_in_fully_bound_structs = "warn"
same_functions_in_if_condition = "warn"
string_lit_as_bytes = "warn"
suboptimal_flops = "warn"
suspicious_operation_groupings = "warn"
suspicious_xor_used_as_pow = "warn"
trailing_empty_array = "warn"
trait_duplication_in_bounds = "warn"
transmute_ptr_to_ptr = "warn"
transmute_undefined_repr = "warn"
try_err = "warn"
type_repetition_in_bounds = "warn"
unchecked_duration_subtraction = "warn"
unicode_not_nfc = "warn"
unnecessary_join = "warn"
unnecessary_self_imports = "warn"
unnecessary_struct_initialization = "warn"
unnecessary_wraps = "warn"
unnested_or_patterns = "warn"
unused_async = "warn"
unused_peekable = "warn"
unused_rounding = "warn"
useless_let_if_seq = "warn"
useless_transmute = "warn"
verbose_bit_mask = "warn"
wildcard_dependencies = "warn"
zero_sized_map_values = "warn"
[lints.clippy.nursery]
level = "warn"
priority = -2
[lints.clippy.pedantic]
level = "warn"
priority = -1
[lints.rust]
deprecated_safe = "warn"
elided_lifetimes_in_paths = "warn"
explicit_outlives_requirements = "warn"
ffi_unwind_calls = "warn"
let_underscore_drop = "warn"
macro_use_extern_crate = "warn"
meta_variable_misuse = "warn"
missing_abi = "warn"
missing_debug_implementations = "warn"
missing_docs = "warn"
missing_unsafe_on_extern = "warn"
non_ascii_idents = "warn"
non_local_definitions = "warn"
redundant_lifetimes = "warn"
single_use_lifetimes = "warn"
trivial_casts = "warn"
trivial_numeric_casts = "warn"
unit_bindings = "warn"
unnameable_types = "warn"
unreachable_pub = "warn"
unsafe_code = "warn"
unstable_features = "warn"
unused_extern_crates = "warn"
unused_import_braces = "warn"
unused_lifetimes = "warn"
unused_macro_rules = "warn"
unused_qualifications = "warn"
variant_size_differences = "warn"
[lints.rust.rust_2024_compatibility]
level = "warn"
priority = 1
[lints.rust.tail_expr_drop_order]
level = "allow"
priority = 2
[lints.rust.unexpected_cfgs]
level = "warn"
priority = 0
check-cfg = ["cfg(nightly)"]
[lints.rustdoc]
missing_crate_level_docs = "warn"
unescaped_backticks = "warn"
bon-3.7.1/Cargo.toml.orig 0000644 0000000 0000000 00000006567 10461020230 0013317 0 ustar 0000000 0000000 [package]
name = "bon"
version = "3.7.1"
description = "Next-gen compile-time-checked builder generator, named function's arguments, and more!"
categories = [
"rust-patterns",
"data-structures",
"asynchronous",
"no-std",
"no-std::no-alloc",
]
keywords = ["builder", "macro", "derive", "constructor", "setter"]
edition = "2021"
homepage = "https://bon-rs.com"
license = "MIT OR Apache-2.0"
repository = "https://github.com/elastio/bon"
# This MSRV was chosen because Rust supports mixing generic type and const
# parameters only starting with this version. We require this feature for the
# cases when the builder is generated for a function or struct that uses const
# generics. The generated builder **always** appends a generic type parameter
# for the type state at the end of the Builder generics list. So for functions
# or structs that use const generics the generated builder will have a generic
# type parameter after the const generic parameter, which is only supported
# starting from Rust 1.59.0.
rust-version = "1.59.0"
[package.metadata.docs.rs]
all-features = true
# Generate clickable links in the source code view in the docs
rustdoc-args = ["--generate-link-to-definition"]
# We don't need the docs to be built for every first-tier target.
# This crate is not platform-specific.
targets = ["x86_64-unknown-linux-gnu"]
[lints]
workspace = true
[dependencies]
# The version of the macro crate is pinned to a specific one because the code
# generated by the macros uses private APIs from the runtime crate that are not
# guarded by semver.
bon-macros = { path = "../bon-macros", version = "=3.7.1" }
rustversion = "1"
[dev-dependencies]
# Using a bit older version that supports our MSRV
expect-test = "1.4.1"
# Using a bit older version that supports our MSRV
tokio = { version = "1.29.1", features = ["macros", "rt"] }
macro_rules_attribute = "0.2"
# Using a bit older version that supports our MSRV
trybuild = "1.0.89"
[features]
alloc = ["bon-macros/alloc"]
default = ["std"]
std = ["bon-macros/std", "alloc"]
# See the explanation of what this feature does in the docs here:
# https://bon-rs.com/guide/typestate-api/custom-methods#implied-bounds
implied-bounds = ["bon-macros/implied-bounds"]
# 🔬 Experimental! There may be breaking changes to this feature between *minor* releases,
# however, compatibility within patch releases is guaranteed though.
#
# This feature enables the #[builder(overwritable)] attribute that can be used to
# allow overwriting already set fields in the builder. Without this attribute it's
# not possible to set the same member twice in the builder, a compile error would be
# generated.
#
# See more info at https://bon-rs.com/reference/builder/top-level/overwritable.
#
# We are considering stabilizing this attribute if you have a use for it. Please leave
# a 👍 reaction under the issue https://github.com/elastio/bon/issues/149 if you need
# this attribute. It would also be cool if you could leave a comment under that issue
# describing your use case for it.
experimental-overwritable = ["bon-macros/experimental-overwritable"]
# Legacy experimental attribute. It's left here for backwards compatibility,
# and it will be removed in the next major release.
#
# We've stabilized the MVP of this feature, so it's no longer experimental.
# The tracking issue for this feature: https://github.com/elastio/bon/issues/225.
experimental-getter = []
bon-3.7.1/README.md 0000644 0000000 0000000 00000020160 10461020230 0011670 0 ustar 0000000 0000000
# 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` has to offer.
## 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/basics/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.
| ⭐ 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. If you want to learn more, jump to the [Basics](https://bon-rs.com/guide/basics) section. And remember: knowledge is power 🐱!
Feel free to jump to code and use the `#[builder]` and `#[derive(Builder)]` once you've seen enough docs to get started.
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 = "3.7"
```
You can opt out of `std` and `alloc` cargo features with `default-features = false` for `no_std` environments.
## Acknowledgments
This project was heavily inspired by such awesome crates as [`buildstructor`](https://docs.rs/buildstructor), [`typed-builder`](https://docs.rs/typed-builder) and [`derive_builder`](https://docs.rs/derive_builder). This crate was designed with many lessons learned from them.
See [alternatives](https://bon-rs.com/guide/alternatives) for comparison.
## Supporters
Big thanks to `bon`'s current financial supporters ❤️
**Ethan Skowronski**\
$1/month
**Julius Lungys**\
$1/month
## Past Supporters
Big thanks to `bon`'s past financial supporters ❤️
[](https://kindness.ai)\
[**Kindness**](https://kindness.ai)
## Who's Using `bon`?
Some notable open-source users: [`crates.io` backend](https://github.com/rust-lang/crates.io), [`tantivy`](https://github.com/quickwit-oss/tantivy), [`apache-avro`](https://github.com/apache/avro-rs), [`google-cloud-auth`](https://github.com/googleapis/google-cloud-rust), [`comrak`](https://github.com/kivikakk/comrak), [`ractor`](https://github.com/slawlor/ractor).
## 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
Discord
Here you can leave feedback, ask questions, report bugs, etc.
## 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.
bon-3.7.1/src/__/better_errors.rs 0000644 0000000 0000000 00000001635 10461020230 0015012 0 ustar 0000000 0000000 //! Utility functions for improving error messages in builder's generated code.
//!
//! These free functions are simple wrappers over the respective traits. They allow the
//! generated code to pass the concrete type of the member using the turbofish syntax,
//! which improves the compile errors when the member's type `T` doesn't implement
//! the target trait.
//!
//! They improve the spans of error messages because compiler knows that it needs to
//! point to the origin of the offending type (member's type T) from the turbofish
//! syntax to where the type came from (original code written by the user).
use core::fmt::Debug;
#[inline(always)]
pub fn clone_member(member: &Option) -> Option {
member.clone()
}
#[inline(always)]
pub fn as_dyn_debug(member: &T) -> &dyn Debug {
member
}
#[inline(always)]
pub fn copy_member(member: &Option) -> Option {
*member
}
bon-3.7.1/src/__/cfg_eval.rs 0000644 0000000 0000000 00000011577 10461020230 0013705 0 ustar 0000000 0000000 /// This is all a big embarrassing workaround, please don't oversee 😳😳😳.
///
/// Anyway, if you are curious what the hell is going on here, then here is
/// an explanation 😸. So... where to start 🤔. Ah! The problem!
///
/// ## The problem
///
/// Proc macro attributes (like `#[builder]`) see all the `#[cfg(...)]` and `#[cfg_attr(...)]`
/// attributes unexpanded. For example, if you write smth like this:
///
/// ```
/// #[bon::builder]
/// fn func(
/// #[cfg(windows)]
/// windows_only_param: u32,
/// ) {}
///
/// ```
///
/// then the `#[builder]` macro will see the full `#[cfg(...)]` attribute with
/// the `windows_only_param` it is attached to verbatim. The `#[cfg(...)]` isn't
/// removed by the time the `#[builder]`'s macro expansion is invoked.
///
/// It is a problem because the `#[builder]` macro needs to know the exact list
/// of members it has to generate setters for. It doesn't know whether
/// the `windows` predicate evaluates to `true` or `false`, especially if this was
/// a more complex predicate. So it can't decide whether to generate a setter for
/// the `windows_only_param` or not.
///
/// ## The solution
///
/// This macro allows us to evaluate the `cfg` predicates by using a variation of
/// [the trick] shared by @recatek.
///
/// When the `#[builder]` macro finds any usage of `#[cfg(...)]` or `#[cfg_attr(...)]`
/// it generates a call to this macro with all `cfg` predicates collected from the
/// item it was placed on. The `#[builder]` macro deduplicates and sorts the `cfg`
/// predicates and passes them as `$pred` to this macro.
///
/// This macro then dispatches to `__eval_cfg_callback_true` or `__eval_cfg_callback_false`
/// by defining a conditional `use ...` statement for each predicate and collects the
/// results of the evaluation in the `$results` list.
///
/// For the last call to this macro (when no more `$pred` are left) the macro calls back
/// to the proc macro attribute that called it with the results of the evaluation and
/// the original parameters and the item which are passed through via the `$rest` macro variable.
///
/// [the trick]: https://users.rust-lang.org/t/supporting-or-evaluating-cfg-in-proc-macro-parameters/93240/2
#[macro_export]
#[doc(hidden)]
macro_rules! __eval_cfg_callback {
(
{ $($results:tt)* }
( $pred_id:ident: $($pred:tt)* )
$($rest:tt)*
) => {
// The `pred_id` is required to be a unique identifier for the current
// predicate evaluation so that we can use it in a `use` statement to define
// a new unique name for the macro to call.
#[cfg($($pred)*)]
#[doc(hidden)]
#[allow(deprecated)]
use $crate::__eval_cfg_callback_true as $pred_id;
#[cfg(not($($pred)*))]
#[doc(hidden)]
#[allow(deprecated)]
use $crate::__eval_cfg_callback_false as $pred_id;
// The trick here is that `$pred_id` now resolves either to
// `__eval_cfg_callback_true` or `__eval_cfg_callback_false`
// depending on the evaluation of the cfg predicate, so by
// invoking it as a macro, that macro internally pushes either
// `true` or `false` to the `$results` list.
$pred_id! {
{ $($results)* }
$($rest)*
}
};
// The terminal case for the recursion when there are no more predicates left.
// We have collected all the results of the cfg evaluations and now we can
// delegate them to the proc macro attribute that called this macro.
(
// The results of the cfg evaluation
{ $($results:tt)* }
// The proc macro attribute to invoke with the results
$final_macro:path,
// The number of times this macro was called recursively from the proc macro
$recursion_counter:literal,
// Parameters to pass to the proc macro attribute after the cfg results
( $($macro_params:tt)* )
// The item to attach the proc macro attribute to
$($item:tt)*
) => {
// The special `__cfgs(...)` prefix is parsed by the proc macro attribute
// to get the results of the cfg evaluations.
#[$final_macro(__cfgs($recursion_counter, $($results)*) $($macro_params)*)]
$($item)*
};
}
/// The `cfg` predicate evaluated to `true`, now push that information into
/// the `$results` list.
#[macro_export]
#[doc(hidden)]
macro_rules! __eval_cfg_callback_true {
(
{ $($results:tt)* }
$($tt:tt)*
) => {
$crate::__eval_cfg_callback! {
{ $($results)* true, }
$($tt)*
}
};
}
/// The `cfg` predicate evaluated to `false`, now push that information into
/// the `$results` list.
#[macro_export]
#[doc(hidden)]
macro_rules! __eval_cfg_callback_false {
(
{ $($results:tt)* }
$($tt:tt)*
) => {
$crate::__eval_cfg_callback! {
{ $($results)* false, }
$($tt)*
}
};
}
bon-3.7.1/src/__/ide.rs 0000644 0000000 0000000 00000012553 10461020230 0012673 0 ustar 0000000 0000000 #![allow(
non_upper_case_globals,
missing_debug_implementations,
clippy::wildcard_imports
)]
/// Completions for the top-level `builder` attribute.
pub mod builder_top_level {
use super::*;
/// See the docs at
pub const builder_type: Option = None;
pub mod builder_type {
use super::*;
/// See the docs at
pub const name: Identifier = Identifier;
/// See the docs at
pub const vis: VisibilityString = VisibilityString;
/// See the docs at
pub const doc: DocComments = DocComments;
}
/// See the docs at
pub const finish_fn: Option = None;
/// See the docs at
pub mod finish_fn {
use super::*;
/// See the docs at
pub const name: Identifier = Identifier;
/// See the docs at
pub const vis: VisibilityString = VisibilityString;
/// See the docs at
pub const doc: DocComments = DocComments;
}
/// See the docs at
pub const start_fn: Option = None;
/// See the docs at
pub mod start_fn {
use super::*;
/// See the docs at
pub const name: Identifier = Identifier;
/// See the docs at
pub const vis: VisibilityString = VisibilityString;
/// See the docs at
pub const doc: DocComments = DocComments;
}
/// See the docs at
pub const state_mod: Option = None;
/// See the docs at
pub mod state_mod {
use super::*;
/// See the docs at
pub const name: Identifier = Identifier;
/// See the docs at
pub const vis: VisibilityString = VisibilityString;
/// See the docs at
pub const doc: DocComments = DocComments;
}
/// See the docs at
pub mod on {
use super::*;
/// See the docs at
pub const into: Flag = Flag;
/// See the docs at
pub const required: Flag = Flag;
/// See the docs at
pub const overwritable: Flag = Flag;
}
/// See the docs at
pub mod derive {
/// See the docs at
pub use core::fmt::Debug;
/// See the docs at
pub use core::clone::Clone;
/// See the docs at
pub use core::convert::Into;
/// See the docs at
#[rustversion::since(1.64)]
pub use core::future::IntoFuture;
}
/// The real name of this parameter is `crate` (without the underscore).
/// 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
pub const crate_: Option = None;
}
/// Visibility inside of a string literal. Empty string means private visibility.
///
/// Examples:
///
/// - `""` - the symbol is private (accessible only within the same module)
/// - `"pub"` - the symbol is accessible outside of the crate
/// - `"pub(crate)"` - the symbol is accessible anywhere inside of the crate, but not outside of it
///
/// [Rust reference](https://doc.rust-lang.org/reference/visibility-and-privacy.html)
pub struct VisibilityString;
/// [Rust reference](https://doc.rust-lang.org/reference/identifiers.html)
pub struct Identifier;
/// The presence of this attribute enables the behavior. The attribute has no value.
pub struct Flag;
/// Documentation comments using the syntax `/// doc comment here`.
///
/// [Rust reference](https://doc.rust-lang.org/reference/comments.html#doc-comments)
pub struct DocComments;
/// Simple path that is valid in a `use` statement. Example: `foo::bar::baz`.
///
/// [Rust reference](https://doc.rust-lang.org/reference/paths.html?highlight=path#simple-paths)
pub struct Path;
bon-3.7.1/src/__/mod.rs 0000644 0000000 0000000 00000002613 10461020230 0012705 0 ustar 0000000 0000000 #![allow(
// We place `#[inline(always)]` only on very small methods where we'd event want
// a guarantee of them being inlined.
clippy::inline_always,
// Marking every potential function as `const` is a bit too much.
// Especially, this doesn't play well with our MSRV. Trait bounds
// aren't allowed on const functions in older Rust versions.
clippy::missing_const_for_fn,
)]
/// Used for providing better IDE hints (completions and syntax highlighting).
pub mod ide;
pub mod better_errors;
mod cfg_eval;
// This reexport is a private implementation detail and should not be used
// directly! This reexport may change or be removed at any time between
// patch releases. Use the export from your generated builder's state module
// directly instead of using this reexport from `bon::__`.
pub use crate::builder_state::{IsSet, IsUnset};
pub use bon_macros::__privatize;
pub use rustversion;
pub(crate) mod sealed {
// The purpose of the `Sealed` trait **is** to be unnameable from outside the crate.
#[allow(unnameable_types)]
pub trait Sealed: Sized {}
impl Sealed for super::Unset {}
impl Sealed for super::Set {}
}
pub(crate) use sealed::Sealed;
/// Used to implement the `alloc` feature.
#[cfg(feature = "alloc")]
pub extern crate alloc;
#[derive(Debug)]
pub struct Unset(Name);
#[derive(Debug)]
pub struct Set(Name);
bon-3.7.1/src/builder_state.rs 0000644 0000000 0000000 00000002723 10461020230 0014401 0 ustar 0000000 0000000 //! The items here are intentionally defined in a private module not inside of the
//! [`crate::__`] module. This is because that module is marked with `#[deprecated]`
//! which makes all items defined in that module also deprecated.
//!
//! This is not the desired behavior for the items defined here. They are not deprecated,
//! and they are expected to be exposed to the users. However, the users must not reference
//! them through the `bon` crate. Instead, they should use the re-exports from the state
//! module generated for the builder.
use crate::__::{Sealed, Set, Unset};
/// Marker trait that indicates that the member is set, i.e. at least
/// one of its setters was called.
#[rustversion::attr(
since(1.78.0),
diagnostic::on_unimplemented(
message = "the member `{Self}` was not set, but this method requires it to be set",
label = "the member `{Self}` was not set, but this method requires it to be set"
)
)]
pub trait IsSet: Sealed {}
/// Marker trait that indicates that the member is unset, i.e. none
/// of its setters was called.
#[rustversion::attr(
since(1.78.0),
diagnostic::on_unimplemented(
message = "the member `{Self}` was already set, but this method requires it to be unset",
label = "the member `{Self}` was already set, but this method requires it to be unset"
)
)]
pub trait IsUnset: Sealed {}
#[doc(hidden)]
impl IsSet for Set {}
#[doc(hidden)]
impl IsUnset for Unset {}
bon-3.7.1/src/collections.rs 0000644 0000000 0000000 00000011716 10461020230 0014073 0 ustar 0000000 0000000 /// Same as [`std::vec!`] but converts each element with [`Into`].
///
/// **WARNING:** it's not recommended to import this macro into scope. Reference it
/// using the full path (`bon::vec![]`) to avoid confusion with the [`std::vec!`] macro.
///
/// A good example of the use case for this macro is when you want to create a
/// [`Vec`] where part of the items are hard-coded string literals of type
/// `&str` and the other part is made of dynamic [`String`] values.
///
/// ```
/// fn convert_media(input_extension: &str, output_extension: &str) -> std::io::Result<()> {
/// let ffmpeg_args: Vec = bon::vec![
/// "-i",
/// format!("input.{input_extension}"),
/// "-y",
/// format!("output.{output_extension}"),
/// ];
///
/// std::process::Command::new("ffmpeg").args(ffmpeg_args).output()?;
///
/// Ok(())
/// }
/// ```
///
/// This macro doesn't support `vec![expr; N]` syntax, since it's simpler to
/// just write `vec![expr.into(); N]` using [`std::vec!`] instead.
#[macro_export]
#[cfg(feature = "alloc")]
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
#[allow(edition_2024_expr_fragment_specifier)]
macro_rules! vec {
() => ($crate::__::alloc::vec::Vec::new());
($($item:expr),+ $(,)?) => ($crate::__::alloc::vec![$(::core::convert::Into::into($item)),+ ]);
}
/// Creates a fixed-size array literal with each element converted with [`Into`].
///
/// You'll probably need a hint for the target type of items in the array if the
/// compiler can't infer it from its usage.
///
/// This is similar in spirit to the [`bon::vec!`] macro, but it's for arrays.
/// See [`bon::vec!`] docs for details.
///
/// Same example as in [`bon::vec!`], but using this macro. It works with array
/// as well because [`Command::args`] accepts any value that implements [`IntoIterator`]:
///
/// ```
/// fn convert_media(input_extension: &str, output_extension: &str) -> std::io::Result<()> {
/// let ffmpeg_args: [String; 4] = bon::arr![
/// "-i",
/// format!("input.{input_extension}"),
/// "-y",
/// format!("output.{output_extension}"),
/// ];
///
/// std::process::Command::new("ffmpeg").args(ffmpeg_args).output()?;
///
/// Ok(())
/// }
/// ```
///
/// This macro doesn't support `[expr; N]` syntax, since it's simpler to
/// just write `[expr.into(); N]` instead.
///
/// [`Command::args`]: std::process::Command::args
/// [`bon::vec!`]: crate::vec
#[macro_export]
#[allow(edition_2024_expr_fragment_specifier)]
macro_rules! arr {
() => ([]);
($($item:expr),+ $(,)?) => ([$(::core::convert::Into::into($item)),+]);
}
#[cfg(test)]
mod tests {
// It's okay to use indexing in tests for conciseness.
#![allow(clippy::indexing_slicing)]
#[cfg(feature = "alloc")]
use crate::__::alloc::{string::String, vec::Vec};
use core::num::NonZeroU8;
#[cfg(feature = "alloc")]
#[test]
fn arr_of_strings() {
let actual: [String; 3] = crate::arr!["foo", "bar", "baz"];
assert_eq!(actual, ["foo", "bar", "baz"]);
let actual: [String; 0] = crate::arr![];
assert!(actual.is_empty());
}
#[test]
fn arr_of_numbers() {
let actual: [u8; 2] = crate::arr![NonZeroU8::new(1).unwrap(), NonZeroU8::new(2).unwrap()];
assert_eq!(actual, [1, 2]);
let actual: [u8; 0] = crate::arr![];
assert!(actual.is_empty());
}
#[cfg(feature = "alloc")]
#[test]
fn vec_smoke() {
let actual: Vec = crate::vec!["foo", "bar", "baz"];
assert_eq!(actual, ["foo", "bar", "baz"]);
let actual: Vec = crate::vec![];
assert!(actual.is_empty());
}
#[cfg(feature = "std")]
#[test]
fn map_smoke() {
use std::collections::{BTreeMap, HashMap};
let hash_strings: HashMap = crate::map! {
"Hello": "World",
"Goodbye": "Mars",
};
assert_eq!(hash_strings["Hello"], "World");
assert_eq!(hash_strings["Goodbye"], "Mars");
let tree_strings: BTreeMap = crate::map! {
"Hello": "World",
"Goodbye": "Mars",
};
assert_eq!(tree_strings["Hello"], "World");
assert_eq!(tree_strings["Goodbye"], "Mars");
}
#[cfg(feature = "std")]
#[test]
fn set_smoke() {
use std::collections::BTreeSet;
use std::collections::HashSet;
let hash_strings: HashSet = crate::set!["Hello", "World", "Goodbye", "Mars"];
assert!(hash_strings.contains("Hello"));
assert!(hash_strings.contains("World"));
assert!(hash_strings.contains("Goodbye"));
assert!(hash_strings.contains("Mars"));
let tree_strings: BTreeSet = crate::set!["Hello", "World", "Goodbye", "Mars"];
assert!(tree_strings.contains("Hello"));
assert!(tree_strings.contains("World"));
assert!(tree_strings.contains("Goodbye"));
assert!(tree_strings.contains("Mars"));
}
}
bon-3.7.1/src/lib.rs 0000644 0000000 0000000 00000002307 10461020230 0012317 0 ustar 0000000 0000000 #![doc(
html_logo_url = "https://bon-rs.com/bon-logo-thumb.png",
html_favicon_url = "https://bon-rs.com/bon-logo-medium.png"
)]
#![doc = include_str!("../README.md")]
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(docsrs, feature(doc_cfg))]
// We mark all items from the `private` module as deprecated to signal that they are
// implementation details and should not be used directly. Unfortunately, this triggers
// the deprecation warnings within this crate itself everywhere we use them, so we just
// suppress this lint for the entire crate.
#![allow(deprecated)]
// Rexport all macros from the proc-macro crate.
pub use bon_macros::{bon, builder, map, set, Builder};
/// Small utility declarative macros for creating colletions with [`Into`] conversions.
mod collections;
#[doc(hidden)]
#[deprecated = "the items from the `bon::__` module are an implementation detail; \
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://bon-rs.com/discord)"]
pub mod __;
mod builder_state;
bon-3.7.1/tests/integration/builder/attr_bon.rs 0000644 0000000 0000000 00000014630 10461020230 0017707 0 ustar 0000000 0000000 use crate::prelude::*;
use core::pin::Pin;
#[test]
fn new_method_special_case() {
struct Sut;
#[bon]
impl Sut {
#[builder]
fn new() {}
}
let _: SutBuilder = Sut::builder();
let builder: SutBuilder = Sut::builder();
builder.build();
}
#[test]
fn builder_method_special_case() {
struct Sut;
#[bon]
impl Sut {
#[builder]
fn builder() {}
}
let _: SutBuilder = Sut::builder();
let builder: SutBuilder = Sut::builder();
builder.build();
}
#[test]
fn builder_start_fn_is_not_special_case() {
struct Sut;
#[bon]
impl Sut {
#[builder(start_fn = builder)]
fn some_other_name() {}
}
let _: SutSomeOtherNameBuilder = Sut::builder();
let builder: SutSomeOtherNameBuilder = Sut::builder();
builder.call();
Sut::some_other_name();
}
#[test]
fn receiver_variations() {
#[derive(Clone)]
struct Sut {
field: u32,
}
#[bon]
impl Sut {
#[builder]
#[allow(clippy::use_self)]
fn self_as_ref_sut(self: &Sut) -> u32 {
self.field
}
#[builder]
fn mut_self(mut self) -> Self {
self.field += 1;
self
}
#[builder]
fn ref_mut_self(&mut self) {
self.field += 1;
}
#[builder]
fn mut_self_ref_self(#[allow(clippy::needless_arbitrary_self_type)] mut self: &Self) {
#[allow(clippy::self_assignment, unused_assignments)]
{
self = &Self { field: 43 };
}
}
#[builder]
fn mut_self_as_ref_mut_self(
#[allow(clippy::needless_arbitrary_self_type)] mut self: &mut Self,
) {
self.field = 45;
#[allow(clippy::self_assignment, unused_assignments, dead_code)]
{
self = self;
}
}
#[builder]
fn self_as_pin_mut_self(self: Pin<&mut Self>) {
let _ = self;
}
#[builder]
fn mut_self_as_pin_mut_self(mut self: Pin<&mut Self>) {
#[allow(clippy::self_assignment, unused_assignments)]
{
self = self;
}
}
}
let mut sut = Sut { field: 42 };
Sut::self_as_ref_sut(&sut).call();
sut.self_as_ref_sut().call();
Sut::mut_self(sut.clone()).call();
sut.clone().mut_self().call();
Sut::mut_self_ref_self(&sut).call();
sut.mut_self_ref_self().call();
Sut::ref_mut_self(&mut sut).call();
sut.ref_mut_self().call();
assert_eq!(sut.field, 44);
Sut::mut_self_as_ref_mut_self(&mut sut).call();
sut.mut_self_as_ref_mut_self().call();
assert_eq!(sut.field, 45);
Sut::self_as_pin_mut_self(Pin::new(&mut sut)).call();
Pin::new(&mut sut).self_as_pin_mut_self().call();
}
#[cfg(feature = "alloc")]
#[test]
fn receiver_variations_alloc() {
use core::pin::Pin;
#[derive(Clone)]
struct Sut {
field: u32,
}
#[bon]
impl Sut {
#[builder]
fn mut_self_as_box(mut self: Box) {
self.field += 1;
drop(self);
}
#[builder]
fn self_as_box(self: Box) {
drop(self);
}
#[builder]
fn self_as_rc(self: Rc) {
drop(self);
}
#[builder]
fn self_as_arc(self: Arc) {
drop(self);
}
#[builder]
fn self_as_pin_box_self(self: Pin>) {
drop(self);
}
#[builder]
#[allow(clippy::use_self)]
fn self_as_pin_box_sut(self: Pin>) {
drop(self);
}
}
let sut = Sut { field: 42 };
Sut::mut_self_as_box(Box::new(sut.clone())).call();
Box::new(sut.clone()).mut_self_as_box().call();
Sut::self_as_box(Box::new(sut.clone())).call();
Box::new(sut.clone()).self_as_box().call();
Sut::self_as_rc(Rc::new(sut.clone())).call();
Rc::new(sut.clone()).self_as_rc().call();
Sut::self_as_arc(Arc::new(sut.clone())).call();
Arc::new(sut.clone()).self_as_arc().call();
Sut::self_as_pin_box_self(Pin::new(Box::new(sut.clone()))).call();
Pin::new(Box::new(sut.clone()))
.self_as_pin_box_self()
.call();
Sut::self_as_pin_box_sut(Pin::new(Box::new(sut.clone()))).call();
Pin::new(Box::new(sut)).self_as_pin_box_sut().call();
}
#[test]
fn constructor() {
struct Counter {
val: u32,
}
#[bon]
impl Counter {
#[builder(start_fn = builder)]
fn new(initial: Option) -> Self {
Self {
val: initial.unwrap_or_default(),
}
}
}
let counter = Counter::builder().initial(3).build();
assert_eq!(counter.val, 3);
let counter = Counter::new(Some(32));
assert_eq!(counter.val, 32);
}
#[test]
fn receiver() {
#[derive(Clone)]
struct Counter {
val: u32,
}
#[bon]
impl Counter {
/// Docs on the method.
/// Multiline
#[builder]
fn increment(&self, #[builder(default)] disabled: bool) -> Self {
if disabled {
return self.clone();
}
Self { val: self.val + 1 }
}
}
let counter = Counter { val: 0 };
let counter = counter.increment().call();
assert_eq!(counter.val, 1);
}
#[test]
fn receiver_with_lifetimes() {
struct Sut<'a, 'b> {
a: &'a str,
b: &'b str,
}
#[bon]
impl Sut<'_, '_> {
#[builder]
fn method(&self, c: &str) -> usize {
let Self { a, b } = self;
a.len() + b.len() + c.len()
}
}
let actual = Sut { a: "a", b: "b" }.method().c("c").call();
assert_eq!(actual, 3);
}
#[test]
fn self_in_a_bunch_of_places() {
struct Sut;
#[bon]
impl Sut
where
Self: Sized + 'static,
{
#[builder]
fn method(&self, me: Option) -> impl Iterator-
where
Self: Sized,
{
let _ = self;
me.into_iter()
}
}
assert_eq!(Sut.method().me(Sut).call().count(), 1);
}
#[test]
fn impl_block_ty_contains_a_reference() {
struct Sut
(T);
#[bon]
impl Sut<&'_ T> {
#[builder]
fn get(&self) -> &T {
self.0
}
}
assert_eq!(Sut(&42).get().call(), &42);
}
bon-3.7.1/tests/integration/builder/attr_builder.rs 0000644 0000000 0000000 00000001375 10461020230 0020561 0 ustar 0000000 0000000 mod multiple_attributes {
use crate::prelude::*;
#[test]
fn test_struct() {
#[derive(Builder)]
#[builder(start_fn = start)]
#[builder(finish_fn = finish)]
struct Sut {}
let _ = Sut::start().finish();
}
#[test]
fn test_function() {
#[builder]
#[builder]
#[builder(start_fn = start)]
#[builder(finish_fn = finish)]
fn sut() {}
start().finish();
}
#[test]
fn test_method() {
struct Sut {}
#[bon]
impl Sut {
#[builder]
#[builder]
#[builder(start_fn = start)]
#[builder(finish_fn = finish)]
fn method() {}
}
Sut::start().finish();
}
}
bon-3.7.1/tests/integration/builder/attr_const.rs 0000644 0000000 0000000 00000014421 10461020230 0020255 0 ustar 0000000 0000000 #[rustversion::since(1.61.0)]
mod msrv_1_61 {
mod smoke {
use crate::prelude::*;
#[test]
const fn test_struct() {
#[derive(Builder)]
#[builder(const)]
struct Sut {
#[builder(start_fn)]
x1: u32,
// There was a bug in `#[builder(field)]` `const` support, that
// this is testing for: https://github.com/elastio/bon/issues/290
#[builder(field = 11)]
x2: u32,
#[builder(finish_fn)]
x3: u32,
x4: u32,
x5: Option,
#[builder(default = x1 + 99)]
x6: u32,
#[builder(with = |a: u32, b: u32| a + b)]
x7: u32,
#[builder(with = |a: u32, b: u32| -> Result<_, ()> { Ok(a + b) })]
x8: Option,
#[builder(skip = 10)]
x9: u32,
//
// This doesn't work because Rust complains about this in setters that
// consume `self` and return a new instance of the builder:
// ```
// destructor of `builder::attr_const::test_struct::SutBuilder`
// cannot be evaluated at compile-time
// ```
// x7: Vec,
// x8: String,
}
const ACTUAL: Sut = Sut::builder(1).x4(2).x5(3).x7(4, 5).build(6);
#[allow(clippy::assertions_on_constants)]
{
assert!(ACTUAL.x1 == 1);
assert!(ACTUAL.x2 == 11);
assert!(ACTUAL.x3 == 6);
assert!(ACTUAL.x4 == 2);
assert!(matches!(ACTUAL.x5, Some(3)));
assert!(ACTUAL.x6 == 100);
assert!(ACTUAL.x7 == 9);
assert!(ACTUAL.x8.is_none());
assert!(ACTUAL.x9 == 10);
}
}
#[rustversion::since(1.83.0)]
#[test]
const fn test_struct_msrv_1_83() {
#[derive(Builder)]
#[builder(const)]
struct Sut {
#[builder(start_fn)]
#[allow(dead_code)]
x1: u32,
#[builder(field = 11)]
#[allow(dead_code)]
x2: u32,
}
impl SutBuilder {
const fn inc(&mut self) {
self.x1 += 1;
self.x2 += 1;
}
}
let mut builder = Sut::builder(1);
builder.inc();
builder.inc();
assert!(builder.x1 == 3);
assert!(builder.x2 == 13);
}
#[test]
const fn test_function() {
type Output = (u32, u32, u32, u32, Option, u32, u32, Option);
#[builder(const)]
const fn sut(
#[builder(start_fn)] x1: u32,
#[builder(field = 10)] x2: u32,
#[builder(finish_fn)] x3: u32,
x4: u32,
x5: Option,
#[builder(default = x1 + 99)] x6: u32,
#[builder(with = |a: u32, b: u32| a + b)] x7: u32,
#[builder(with = |a: u32, b: u32| -> Result<_, ()> { Ok(a + b) })] x8: Option,
) -> Output {
(x1, x2, x3, x4, x5, x6, x7, x8)
}
const ACTUAL: Output = sut(1).x4(2).x5(3).x7(4, 5).call(6);
#[allow(clippy::assertions_on_constants)]
{
assert!(ACTUAL.0 == 1);
assert!(ACTUAL.1 == 10);
assert!(ACTUAL.2 == 6);
assert!(ACTUAL.3 == 2);
assert!(matches!(ACTUAL.4, Some(3)));
assert!(ACTUAL.5 == 100);
assert!(ACTUAL.6 == 9);
assert!(ACTUAL.7.is_none());
}
}
#[test]
const fn test_method() {
type Output = (u32, u32, u32, u32, Option, u32, u32, Option);
struct Sut;
#[bon]
impl Sut {
#[builder(const)]
const fn sut(
#[builder(start_fn)] x1: u32,
#[builder(field = 10)] x2: u32,
#[builder(finish_fn)] x3: u32,
x4: u32,
x5: Option,
#[builder(default = x1 + 99)] x6: u32,
#[builder(with = |a: u32, b: u32| a + b)] x7: u32,
#[builder(with = |a: u32, b: u32| -> Result<_, ()> { Ok(a + b) })] x8: Option<
u32,
>,
) -> Output {
(x1, x2, x3, x4, x5, x6, x7, x8)
}
}
const ACTUAL: Output = Sut::sut(1).x4(2).x5(3).x7(4, 5).call(6);
#[allow(clippy::assertions_on_constants)]
{
assert!(ACTUAL.0 == 1);
assert!(ACTUAL.1 == 10);
assert!(ACTUAL.2 == 6);
assert!(ACTUAL.3 == 2);
assert!(matches!(ACTUAL.4, Some(3)));
assert!(ACTUAL.5 == 100);
assert!(ACTUAL.6 == 9);
assert!(ACTUAL.7.is_none());
}
}
}
// Tests for the following bug: https://github.com/elastio/bon/issues/287
mod visibility {
use crate::prelude::*;
#[test]
const fn test_struct() {
#[derive(Builder)]
#[builder(const)]
#[allow(unreachable_pub)]
pub struct Sut {
x1: u32,
}
const ACTUAL: Sut = Sut::builder().x1(1).build();
#[allow(clippy::assertions_on_constants)]
{
assert!(ACTUAL.x1 == 1);
}
}
#[test]
const fn test_function() {
#[builder(const)]
pub const fn sut(#[builder(getter)] _x: u32) {}
sut().x(1).call();
}
#[test]
const fn test_method() {
struct Sut;
#[bon]
impl Sut {
#[builder(const)]
pub const fn sut(#[builder(getter)] _x: u32) {}
}
Sut::sut().x(1).call();
}
}
}
bon-3.7.1/tests/integration/builder/attr_crate.rs 0000644 0000000 0000000 00000004770 10461020230 0020233 0 ustar 0000000 0000000 use crate::prelude::*;
use bon as lyra;
#[test]
fn test_struct() {
{
#[derive(Builder)]
#[builder(
crate = crate::builder::attr_crate::lyra,
derive(Debug, Clone)
)]
struct Sut {
_a: u32,
_b: u32,
}
let _ = Sut::builder().a(1).b(2).build();
}
{
macro_rules! in_macro {
() => {
#[derive(Builder)]
#[builder(crate = $crate::builder::attr_crate::lyra, derive(Debug, Clone))]
struct Sut {
_a: u32,
_b: u32,
}
};
}
in_macro!();
let _ = Sut::builder().a(1).b(2).build();
}
{
#[derive(Builder)]
#[builder(
crate = ::bon,
derive(Debug, Clone)
)]
struct Sut {
_a: u32,
_b: u32,
}
let _ = Sut::builder().a(1).b(2).build();
}
}
#[test]
fn test_function() {
{
#[builder(
crate = crate::builder::attr_crate::lyra,
derive(Debug, Clone)
)]
fn sut(_a: u32, _b: u32) {}
sut().a(1).b(2).call();
}
{
macro_rules! in_macro {
() => {
#[builder(crate = $crate::builder::attr_crate::lyra, derive(Debug, Clone))]
fn sut(_a: u32, _b: u32) {}
};
}
in_macro!();
sut().a(1).b(2).call();
}
{
#[builder(
crate = ::bon,
derive(Debug, Clone)
)]
fn sut(_a: u32, _b: u32) {}
sut().a(1).b(2).call();
}
}
#[test]
fn test_method() {
{
struct Sut;
#[bon(crate = crate::builder::attr_crate::lyra)]
impl Sut {
#[builder(derive(Debug, Clone))]
fn sut(_a: u32, _b: u32) {}
}
Sut::sut().a(1).b(2).call();
}
{
macro_rules! in_macro {
() => {
struct Sut;
#[bon(crate = $crate::builder::attr_crate::lyra)]
impl Sut {
#[builder(derive(Debug, Clone))]
fn sut(_a: u32, _b: u32) {}
}
};
}
in_macro!();
Sut::sut().a(1).b(2).call();
}
{
struct Sut;
#[bon(crate = ::bon)]
impl Sut {
#[builder(derive(Debug, Clone))]
fn sut(_a: u32, _b: u32) {}
}
Sut::sut().a(1).b(2).call();
}
}
bon-3.7.1/tests/integration/builder/attr_default.rs 0000644 0000000 0000000 00000022362 10461020230 0020556 0 ustar 0000000 0000000 use crate::prelude::*;
use core::fmt;
#[cfg(feature = "alloc")]
#[test]
fn fn_alloc() {
#[builder]
fn sut(
#[builder(default = "default".to_owned())] arg1: String,
#[builder(default = vec![42])] arg2: Vec,
#[builder(default = "foo", into)] arg3: String,
) -> impl fmt::Debug {
(arg1, arg2, arg3)
}
assert_debug_eq(sut().call(), expect![[r#"("default", [42], "foo")"#]]);
assert_debug_eq(
sut().arg1("arg1".to_owned()).call(),
expect![[r#"("arg1", [42], "foo")"#]],
);
assert_debug_eq(
sut().maybe_arg1(None).call(),
expect![[r#"("default", [42], "foo")"#]],
);
assert_debug_eq(
sut().maybe_arg3(None::).call(),
expect![[r#"("default", [42], "foo")"#]],
);
}
#[cfg(feature = "alloc")]
#[test]
fn struct_alloc() {
use bon::bon;
use expect_test::expect;
#[derive(Debug, Builder)]
struct Sut {
#[builder(default = "default".to_owned())]
arg1: String,
#[builder(default = vec![42])]
arg2: Vec,
#[builder(default = "foo", into)]
arg3: String,
}
assert_debug_eq(
Sut::builder().build(),
expect![[r#"Sut { arg1: "default", arg2: [42], arg3: "foo" }"#]],
);
assert_debug_eq(
Sut::builder().arg1("arg1".to_owned()).build(),
expect![[r#"Sut { arg1: "arg1", arg2: [42], arg3: "foo" }"#]],
);
assert_debug_eq(
Sut::builder().maybe_arg1(None::).build(),
expect![[r#"Sut { arg1: "default", arg2: [42], arg3: "foo" }"#]],
);
#[bon]
#[allow(clippy::items_after_statements)]
impl Sut {
#[builder]
fn assoc(
self,
#[builder(default = "default".to_owned())] arg1: String,
#[builder(default = vec![43])] arg2: Vec,
#[builder(default = "foo", into)] arg3: String,
) -> Self {
Self {
arg1: format!("{}+{arg1}", self.arg1),
arg2: self.arg2.into_iter().chain(arg2).collect(),
arg3: format!("{}+{arg3}", self.arg3),
}
}
}
let sut = || Sut::builder().build();
assert_debug_eq(
sut().assoc().call(),
expect![[r#"
Sut {
arg1: "default+default",
arg2: [
42,
43,
],
arg3: "foo+foo",
}"#]],
);
assert_debug_eq(
sut().assoc().arg1("arg1".to_owned()).call(),
expect![[r#"
Sut {
arg1: "default+arg1",
arg2: [
42,
43,
],
arg3: "foo+foo",
}"#]],
);
assert_debug_eq(
sut().assoc().maybe_arg1(None).call(),
expect![[r#"
Sut {
arg1: "default+default",
arg2: [
42,
43,
],
arg3: "foo+foo",
}"#]],
);
assert_debug_eq(
sut().assoc().maybe_arg3(None::).call(),
expect![[r#"
Sut {
arg1: "default+default",
arg2: [
42,
43,
],
arg3: "foo+foo",
}"#]],
);
}
#[test]
fn fn_no_std() {
#[builder]
fn sut(#[builder(default)] arg1: u32, #[builder(default = 42)] arg2: u32) -> impl fmt::Debug {
(arg1, arg2)
}
assert_debug_eq(sut().call(), expect!["(0, 42)"]);
assert_debug_eq(sut().arg1(12).call(), expect!["(12, 42)"]);
assert_debug_eq(sut().maybe_arg1(None::).call(), expect!["(0, 42)"]);
}
#[test]
fn struct_no_std() {
use bon::bon;
#[derive(Debug, Builder)]
struct Sut {
#[builder(default)]
arg1: u32,
#[builder(default = 42)]
arg2: u32,
}
assert_debug_eq(Sut::builder().build(), expect!["Sut { arg1: 0, arg2: 42 }"]);
assert_debug_eq(
Sut::builder().arg1(12).build(),
expect!["Sut { arg1: 12, arg2: 42 }"],
);
assert_debug_eq(
Sut::builder().maybe_arg1(None::).build(),
expect!["Sut { arg1: 0, arg2: 42 }"],
);
#[bon]
#[allow(clippy::items_after_statements)]
impl Sut {
#[builder]
fn assoc(self, #[builder(default)] arg1: u32, #[builder(default = 43)] arg2: u32) -> Self {
Self {
arg1: self.arg1 + arg1,
arg2: self.arg2 + arg2,
}
}
}
let sut = || Sut::builder().build();
assert_debug_eq(sut().assoc().call(), expect!["Sut { arg1: 0, arg2: 85 }"]);
assert_debug_eq(
sut().assoc().arg1(12).call(),
expect!["Sut { arg1: 12, arg2: 85 }"],
);
assert_debug_eq(
sut().assoc().maybe_arg1(None::).call(),
expect!["Sut { arg1: 0, arg2: 85 }"],
);
}
#[test]
fn fn_generic_default() {
#[builder]
fn sut(
#[builder(default)] arg1: impl Clone + Default,
#[builder(default = <_>::default())] arg2: impl Clone + Default,
) {
drop(arg1);
drop(arg2);
}
sut::<(), ()>().call();
}
mod interaction_with_positional_members {
use crate::prelude::*;
use core::fmt;
#[test]
fn test_struct() {
#[derive(Builder, Debug)]
#[allow(dead_code)]
struct Sut {
#[builder(start_fn)]
starter_1: u32,
#[builder(start_fn)]
starter_2: u32,
#[builder(finish_fn)]
finisher_1: u32,
#[builder(finish_fn)]
finisher_2: u32,
#[builder(default = [starter_1, starter_2, finisher_1, finisher_2])]
named_1: [u32; 4],
#[builder(default = (32, named_1))]
named_2: (u32, [u32; 4]),
}
assert_debug_eq(
Sut::builder(1, 2).build(3, 4),
expect![[r#"
Sut {
starter_1: 1,
starter_2: 2,
finisher_1: 3,
finisher_2: 4,
named_1: [
1,
2,
3,
4,
],
named_2: (
32,
[
1,
2,
3,
4,
],
),
}"#]],
);
assert_debug_eq(
Sut::builder(1, 2).named_1([5, 6, 7, 8]).build(3, 4),
expect![[r#"
Sut {
starter_1: 1,
starter_2: 2,
finisher_1: 3,
finisher_2: 4,
named_1: [
5,
6,
7,
8,
],
named_2: (
32,
[
5,
6,
7,
8,
],
),
}"#]],
);
}
#[test]
fn test_function() {
#[builder]
#[allow(clippy::type_complexity)]
fn sut(
#[builder(start_fn)] starter_1: u32,
#[builder(start_fn)] starter_2: u32,
#[builder(finish_fn)] finisher_1: u32,
#[builder(finish_fn)] finisher_2: u32,
#[builder(default = [starter_1, starter_2, finisher_1, finisher_2])] //
named_1: [u32; 4],
#[builder(default = (32, named_1))] named_2: (u32, [u32; 4]),
) -> impl fmt::Debug {
(
starter_1, starter_2, finisher_1, finisher_2, named_1, named_2,
)
}
assert_debug_eq(
sut(1, 2).call(3, 4),
expect!["(1, 2, 3, 4, [1, 2, 3, 4], (32, [1, 2, 3, 4]))"],
);
assert_debug_eq(
sut(1, 2).named_1([5, 6, 7, 8]).call(3, 4),
expect!["(1, 2, 3, 4, [5, 6, 7, 8], (32, [5, 6, 7, 8]))"],
);
}
#[test]
fn test_method() {
struct Sut;
#[bon]
impl Sut {
#[builder]
#[allow(clippy::type_complexity)]
fn sut(
#[builder(start_fn)] starter_1: u32,
#[builder(start_fn)] starter_2: u32,
#[builder(finish_fn)] finisher_1: u32,
#[builder(finish_fn)] finisher_2: u32,
#[builder(default = [starter_1, starter_2, finisher_1, finisher_2])] //
named_1: [u32; 4],
#[builder(default = (32, named_1))] named_2: (u32, [u32; 4]),
) -> impl fmt::Debug {
(
starter_1, starter_2, finisher_1, finisher_2, named_1, named_2,
)
}
}
assert_debug_eq(
Sut::sut(1, 2).call(3, 4),
expect!["(1, 2, 3, 4, [1, 2, 3, 4], (32, [1, 2, 3, 4]))"],
);
assert_debug_eq(
Sut::sut(1, 2).named_1([5, 6, 7, 8]).call(3, 4),
expect!["(1, 2, 3, 4, [5, 6, 7, 8], (32, [5, 6, 7, 8]))"],
);
}
}
bon-3.7.1/tests/integration/builder/attr_derive.rs 0000644 0000000 0000000 00000022713 10461020230 0020410 0 ustar 0000000 0000000 // We intentionally exercise cloning from `#[builder(derive(Clone))]` here
// to make sure that it works.
#![allow(clippy::redundant_clone)]
use crate::prelude::*;
#[test]
fn smoke_fn() {
#[builder(derive(Clone, Debug, Into))]
fn sut(_arg1: bool, _arg2: Option<()>, _arg3: Option<&str>, _arg4: Option) -> u32 {
99
}
let actual = sut().arg1(true).arg3("value").maybe_arg4(None).clone();
assert_debug_eq(
&actual,
expect![[r#"SutBuilder { arg1: true, arg3: "value" }"#]],
);
let actual: u32 = From::from(actual);
assert_debug_eq(actual, expect!["99"]);
}
#[test]
fn smoke_struct() {
#[derive(Builder, Debug)]
#[builder(derive(Clone, Debug, Into))]
struct Sut<'a> {
_arg1: bool,
_arg2: Option<()>,
_arg3: Option<&'a str>,
_arg4: Option,
}
let actual = Sut::builder()
.arg1(true)
.arg3("value")
.maybe_arg4(None)
.clone();
assert_debug_eq(
&actual,
expect![[r#"SutBuilder { arg1: true, arg3: "value" }"#]],
);
let actual: Sut<'_> = From::from(actual);
assert_debug_eq(
actual,
expect![[r#"
Sut {
_arg1: true,
_arg2: None,
_arg3: Some(
"value",
),
_arg4: None,
}"#]],
);
}
#[test]
fn builder_with_receiver() {
#[derive(Clone, Debug)]
struct Sut {
#[allow(dead_code)]
name: &'static str,
}
#[bon]
impl Sut {
#[builder(derive(Clone, Debug, Into))]
fn method(&self, other_name: &'static str, values: &[u8]) -> u32 {
let _ = (self, other_name, values);
99
}
}
let actual = Sut { name: "Blackjack" }
.method()
.other_name("P21")
.values(&[1, 2, 3])
.clone();
assert_debug_eq(
&actual,
expect![[r#"
SutMethodBuilder {
self_receiver: Sut {
name: "Blackjack",
},
other_name: "P21",
values: [
1,
2,
3,
],
}"#]],
);
let actual: u32 = From::from(actual);
assert_debug_eq(actual, expect!["99"]);
}
#[test]
fn skipped_members() {
struct NoDebug;
#[derive(Builder)]
#[builder(derive(Debug, Clone, Into))]
struct Sut {
arg1: bool,
#[builder(skip = NoDebug)]
_arg2: NoDebug,
}
let actual = Sut::builder().arg1(true).clone();
assert_debug_eq(&actual, expect!["SutBuilder { arg1: true }"]);
let actual: Sut = From::from(actual);
assert!(actual.arg1);
}
#[test]
fn empty_builder() {
#[derive(Builder)]
#[builder(derive(Clone, Debug, Into))]
struct Sut {}
#[allow(clippy::redundant_clone)]
let actual = Sut::builder().clone();
assert_debug_eq(&actual, expect!["SutBuilder"]);
let Sut {} = From::from(actual);
}
mod generics {
use crate::prelude::*;
#[test]
fn test_struct() {
#[derive(Builder, Debug)]
#[builder(derive(Clone, Debug, Into))]
struct Sut
where
T: Clone,
{
_arg1: T,
}
let actual = Sut::builder().arg1(42).clone();
assert_debug_eq(&actual, expect!["SutBuilder { arg1: 42 }"]);
let actual: Sut<_> = From::from(actual);
assert_debug_eq(actual, expect![[r#"Sut { _arg1: 42 }"#]]);
}
#[test]
fn test_function() {
#[builder(derive(Clone, Debug, Into))]
fn sut(_arg1: T) -> u32
where
T: Clone,
{
99
}
let actual = sut::().arg1(42).clone();
assert_debug_eq(&actual, expect!["SutBuilder { arg1: 42 }"]);
let actual: u32 = From::from(actual);
assert_debug_eq(actual, expect!["99"]);
}
#[test]
fn test_method() {
#[derive(Clone, Debug)]
struct Sut(T);
#[bon]
impl Sut
where
T: Clone,
{
#[builder(derive(Clone, Debug, Into))]
fn sut(_arg1: U) -> u32 {
99
}
#[builder(derive(Clone, Debug, Into))]
fn with_self(&self, _arg1: U) -> u32 {
let _ = self;
99
}
}
let actual = Sut::<()>::sut::().arg1(42).clone();
assert_debug_eq(&actual, expect!["SutSutBuilder { arg1: 42 }"]);
let actual: u32 = From::from(actual);
assert_debug_eq(actual, expect!["99"]);
let actual = Sut(true).with_self::().arg1(42).clone();
assert_debug_eq(
&actual,
expect!["SutWithSelfBuilder { self_receiver: Sut(true), arg1: 42 }"],
);
let actual: u32 = From::from(actual);
assert_debug_eq(actual, expect!["99"]);
}
}
mod positional_members {
use crate::prelude::*;
#[test]
fn test_struct() {
#[derive(Builder)]
#[builder(derive(Clone, Debug))]
#[allow(dead_code)]
struct Sut {
#[builder(start_fn)]
start_fn_arg: bool,
#[builder(finish_fn)]
finish_fn_arg: &'static str,
named: u32,
}
let actual = Sut::builder(true);
assert_debug_eq(actual.clone(), expect!["SutBuilder { start_fn_arg: true }"]);
assert_debug_eq(
actual.named(42).clone(),
expect!["SutBuilder { start_fn_arg: true, named: 42 }"],
);
}
#[test]
fn test_function() {
#[builder(derive(Clone, Debug))]
#[allow(unused_variables)]
fn sut(
#[builder(start_fn)] start_fn_arg: bool,
#[builder(finish_fn)] finish_fn_arg: &'static str,
named: u32,
) {
}
let actual = sut(true);
assert_debug_eq(actual.clone(), expect!["SutBuilder { start_fn_arg: true }"]);
assert_debug_eq(
actual.named(42).clone(),
expect!["SutBuilder { start_fn_arg: true, named: 42 }"],
);
}
#[test]
fn test_method() {
#[derive(Debug)]
struct Sut;
#[bon]
#[allow(unused_variables)]
impl Sut {
#[builder(derive(Clone, Debug))]
fn sut(
#[builder(start_fn)] start_fn_arg: bool,
#[builder(finish_fn)] finish_fn_arg: &'static str,
named: u32,
) {
}
#[builder(derive(Clone, Debug))]
fn with_self(
&self,
#[builder(start_fn)] start_fn_arg: bool,
#[builder(finish_fn)] finish_fn_arg: &'static str,
named: u32,
) {
let _ = self;
}
}
let actual = Sut::sut(true);
assert_debug_eq(
actual.clone(),
expect!["SutSutBuilder { start_fn_arg: true }"],
);
assert_debug_eq(
actual.named(42).clone(),
expect!["SutSutBuilder { start_fn_arg: true, named: 42 }"],
);
let actual = Sut.with_self(true);
assert_debug_eq(
actual.clone(),
expect![[r#"
SutWithSelfBuilder {
self_receiver: Sut,
start_fn_arg: true,
}"#]],
);
assert_debug_eq(
actual.named(42).clone(),
expect![[r#"
SutWithSelfBuilder {
self_receiver: Sut,
start_fn_arg: true,
named: 42,
}"#]],
);
}
}
mod attr_bounds_empty {
use crate::prelude::*;
struct NoTraitImpls;
#[test]
fn test_struct() {
#[derive(Builder)]
#[builder(derive(Clone(bounds()), Debug))]
struct Sut<'a, T> {
_arg: &'a T,
}
let _ = Sut::builder().arg(&NoTraitImpls).clone();
}
#[test]
fn test_function() {
#[builder(derive(Clone(bounds()), Debug))]
fn sut(_arg: &T) {}
let _ = sut::().arg(&NoTraitImpls).clone();
}
#[test]
fn test_method() {
#[derive(Clone, Debug)]
struct Sut;
#[bon]
impl Sut {
#[builder(derive(Clone(bounds()), Debug))]
fn sut(_arg: &T) {}
}
let _ = Sut::sut::().arg(&NoTraitImpls).clone();
}
}
mod attr_bounds_non_empty {
use crate::prelude::*;
struct NoTraitImpls;
#[test]
fn test_struct() {
#[derive(Builder)]
#[builder(derive(Clone(bounds(&'a T: Clone, &'a &'a T: Clone)), Debug))]
struct Sut<'a, T> {
_arg: &'a T,
}
let _ = Sut::builder().arg(&NoTraitImpls).clone();
}
#[test]
fn test_function() {
#[builder(derive(Clone(bounds(&'a T: Clone, &'a &'a T: Clone)), Debug))]
#[allow(clippy::needless_lifetimes, single_use_lifetimes)]
fn sut<'a, T>(_arg: &'a T) {}
let _ = sut::().arg(&NoTraitImpls).clone();
}
#[test]
fn test_method() {
#[derive(Clone, Debug)]
struct Sut;
#[bon]
impl Sut {
#[builder(derive(Clone(bounds(&'a T: Clone, &'a &'a T: Clone)), Debug))]
#[allow(clippy::needless_lifetimes, single_use_lifetimes)]
fn sut<'a, T>(_arg: &'a T) {}
}
let _ = Sut::sut::().arg(&NoTraitImpls).clone();
}
}
bon-3.7.1/tests/integration/builder/attr_field.rs 0000644 0000000 0000000 00000010223 10461020230 0020206 0 ustar 0000000 0000000 use crate::prelude::*;
#[test]
fn test_struct() {
#[derive(Builder)]
#[builder(derive(Debug, Clone))]
#[allow(dead_code)]
struct Sut {
#[builder(start_fn)]
x1: u32,
#[builder(start_fn, into)]
x2: u32,
#[builder(field)]
x3: bool,
#[builder(field = x1 + x2 + u32::from(x3))]
x4: u32,
#[builder(field = x4 * 2)]
x5: u32,
#[builder(field)]
x6: Option,
#[builder(field = core::any::type_name::())]
x7: &'static str,
x8: (),
}
// Make sure the builder is cloneable
#[allow(clippy::redundant_clone)]
let sut = Sut::<()>::builder(1, 2_u32).clone();
assert_debug_eq(
&sut,
expect![[r#"
SutBuilder {
x1: 1,
x2: 2,
x3: false,
x4: 3,
x5: 6,
x6: None,
x7: "()",
}"#]],
);
let _ = sut.x8(()).build();
}
// This tests uses a turbofish with `impl Trait`
#[rustversion::since(1.63.0)]
#[test]
fn test_function() {
use core::fmt;
#[builder(derive(Debug, Clone))]
#[allow(unused_variables)]
fn sut(
#[builder(start_fn)] x1: u32,
#[builder(start_fn, into)] x2: u32,
#[builder(field)] x3: bool,
#[builder(field = x1 + x2 + u32::from(x3))] x4: u32,
#[builder(field = x4 * 2)] x5: u32,
#[builder(field)] x6: Option,
#[builder(field = core::any::type_name::())] x7: &'static str,
x8: (),
) {
}
// Make sure the builder is cloneable
#[allow(clippy::redundant_clone)]
let sut = sut::<()>(1, 2_u32).clone();
assert_debug_eq(
&sut,
expect![[r#"
SutBuilder {
x1: 1,
x2: 2,
x3: false,
x4: 3,
x5: 6,
x6: None,
x7: "()",
}"#]],
);
sut.x8(()).call();
}
// This tests uses a turbofish with `impl Trait`
#[rustversion::since(1.63.0)]
#[test]
fn test_method() {
use core::fmt;
#[derive(Debug)]
struct Sut;
#[bon]
impl Sut {
#[builder(derive(Debug, Clone))]
#[allow(unused_variables)]
fn sut(
#[builder(start_fn)] x1: u32,
#[builder(start_fn, into)] x2: u32,
#[builder(field)] x3: bool,
#[builder(field = x1 + x2 + u32::from(x3))] x4: u32,
#[builder(field = x4 * 2)] x5: u32,
#[builder(field)] x6: Option,
#[builder(field = core::any::type_name::())] x7: &'static str,
x8: (),
) {
}
#[builder(derive(Debug, Clone))]
#[allow(unused_variables)]
fn with_self(
&self,
#[builder(start_fn)] x1: u32,
#[builder(start_fn, into)] x2: u32,
#[builder(field)] x3: bool,
#[builder(field = x1 + x2 + u32::from(x3))] x4: u32,
#[builder(field = x4 * 2)] x5: u32,
#[builder(field)] x6: Option,
#[builder(field = core::any::type_name::())] x7: &'static str,
x8: (),
) {
let _ = self;
}
}
// Make sure the builder is cloneable
#[allow(clippy::redundant_clone)]
let sut = Sut::sut::<()>(1, 2_u32).clone();
assert_debug_eq(
&sut,
expect![[r#"
SutSutBuilder {
x1: 1,
x2: 2,
x3: false,
x4: 3,
x5: 6,
x6: None,
x7: "()",
}"#]],
);
sut.x8(()).call();
// Make sure the builder is cloneable
#[allow(clippy::redundant_clone)]
let sut = Sut.with_self::<()>(1, 2_u32).clone();
assert_debug_eq(
&sut,
expect![[r#"
SutWithSelfBuilder {
self_receiver: Sut,
x1: 1,
x2: 2,
x3: false,
x4: 3,
x5: 6,
x6: None,
x7: "()",
}"#]],
);
sut.x8(()).call();
}
bon-3.7.1/tests/integration/builder/attr_getter.rs 0000644 0000000 0000000 00000015374 10461020230 0020431 0 ustar 0000000 0000000 use crate::prelude::*;
#[test]
fn by_ref() {
#[derive(Debug, Builder)]
struct Sut {
#[builder(start_fn)]
_x1: u32,
#[builder(getter(name = x2_with_custom_name))]
_x2: &'static str,
#[builder(getter(vis = "pub(crate)", doc {
/// Docs on the getter
}))]
_x3: u32,
#[builder(into, getter(name = x4_override, vis = "pub(crate)", doc {
/// Docs on getter
}))]
_x4: &'static str,
_no_getter: u32,
#[builder(getter)]
_generic_option: Option,
_x5: (),
#[builder(getter, default)]
_x6: u32,
}
let builder = Sut::builder(0u32)
.x2("2")
.x3(3)
.x4("4")
.no_getter(5)
.x5(())
.maybe_generic_option(None::<()>)
.x6(7);
let actual = (
assert_getter::<&&'static str, _>(&builder, SutBuilder::x2_with_custom_name),
assert_getter::<&u32, _>(&builder, SutBuilder::get_x3),
assert_getter::<&&'static str, _>(&builder, SutBuilder::x4_override),
assert_getter::, _>(&builder, SutBuilder::get_generic_option),
assert_getter:: , _>(&builder, SutBuilder::get_x6),
);
assert_debug_eq(actual, expect![[r#"("2", 3, "4", None, Some(7))"#]]);
}
#[test]
fn clone() {
#[derive(Clone, Debug)]
struct CloneNotCopy(#[allow(dead_code)] u32);
#[derive(Builder)]
struct Sut {
#[builder(getter(clone))]
_x1: CloneNotCopy,
#[builder(getter(clone))]
_x2: Option,
#[builder(getter(clone), default = CloneNotCopy(0))]
_x3: CloneNotCopy,
}
let sut = Sut::builder()
.x1(CloneNotCopy(1))
.x2(CloneNotCopy(2))
.x3(CloneNotCopy(3));
let actual = (
assert_getter::(&sut, SutBuilder::get_x1),
assert_getter::, _>(&sut, SutBuilder::get_x2),
assert_getter:: , _>(&sut, SutBuilder::get_x3),
);
assert_debug_eq(
actual,
expect![[r#"
(
CloneNotCopy(
1,
),
Some(
CloneNotCopy(
2,
),
),
Some(
CloneNotCopy(
3,
),
),
)"#]],
);
}
#[test]
fn copy() {
#[derive(Debug, Builder)]
struct Sut {
#[builder(getter(copy))]
_x1: u32,
#[builder(getter(copy))]
_x2: Option,
#[builder(getter(copy), default)]
_x3: u32,
}
let sut = Sut::builder().x1(1).x2(2).x3(3);
let actual = (
assert_getter::(&sut, SutBuilder::get_x1),
assert_getter::, _>(&sut, SutBuilder::get_x2),
assert_getter:: , _>(&sut, SutBuilder::get_x3),
);
assert_debug_eq(actual, expect!["(1, Some(2), Some(3))"]);
}
#[test]
#[cfg(feature = "std")]
fn deref_implicit() {
use std::borrow::Cow;
use std::ffi::CStr;
use std::ffi::{CString, OsStr, OsString};
use std::path::{Path, PathBuf};
#[derive(Debug, Builder)]
struct Sut<'a> {
#[builder(getter(deref))]
_vec: Vec,
#[builder(getter(deref))]
_optional_vec: Option>,
#[builder(getter(deref), default)]
_default_vec: Vec,
#[builder(getter(deref))]
_box_: Box,
#[builder(getter(deref))]
_rc: Rc,
#[builder(getter(deref))]
_arc: Arc,
#[builder(getter(deref))]
_string: String,
#[builder(getter(deref))]
_c_string: CString,
#[builder(getter(deref))]
_os_string: OsString,
#[builder(getter(deref))]
_path_buf: PathBuf,
#[builder(getter(deref))]
_cow: Cow<'a, str>,
}
let builder = Sut::builder()
.vec(vec![1, 2, 3])
.maybe_optional_vec(None)
.default_vec(vec![0])
.box_(Box::new(4))
.rc(Rc::new(5))
.arc(Arc::new(6))
.string("7".to_string())
.c_string(CString::new("8").unwrap())
.os_string(OsString::from("9"))
.path_buf(PathBuf::from("10"))
.cow(Cow::Borrowed("11"));
let actual = (
assert_getter::<&[u32], _>(&builder, SutBuilder::get_vec),
assert_getter::, _>(&builder, SutBuilder::get_optional_vec),
assert_getter:: , _>(&builder, SutBuilder::get_default_vec),
assert_getter::<&u32, _>(&builder, SutBuilder::get_box_),
assert_getter::<&u32, _>(&builder, SutBuilder::get_rc),
assert_getter::<&u32, _>(&builder, SutBuilder::get_arc),
assert_getter::<&str, _>(&builder, SutBuilder::get_string),
assert_getter::<&CStr, _>(&builder, SutBuilder::get_c_string),
assert_getter::<&OsStr, _>(&builder, SutBuilder::get_os_string),
assert_getter::<&Path, _>(&builder, SutBuilder::get_path_buf),
assert_getter::<&str, _>(&builder, SutBuilder::get_cow),
);
assert_debug_eq(
actual,
expect![[r#"
(
[
1,
2,
3,
],
None,
Some(
[
0,
],
),
4,
5,
6,
"7",
"8",
"9",
"10",
"11",
)"#]],
);
}
#[test]
#[cfg(feature = "std")]
fn deref_explicit() {
use std::rc::Rc;
#[derive(Debug, Builder)]
#[allow(clippy::rc_buffer)]
struct Sut {
// Make sure a deref coercion happens through multiple layers
#[builder(getter(deref(str)))]
_x1: Rc,
#[builder(getter(deref(str)))]
_x2: Option>,
#[builder(getter(deref(str)), default)]
_x3: Rc,
}
let sut = Sut::builder()
.x1(Rc::new("hello".to_owned()))
.x2(Rc::new("world".to_owned()))
.x3(Rc::new("!".to_owned()));
let actual = (
assert_getter::<&str, _>(&sut, SutBuilder::get_x1),
assert_getter::, _>(&sut, SutBuilder::get_x2),
assert_getter:: , _>(&sut, SutBuilder::get_x3),
);
assert_debug_eq(actual, expect![[r#"("hello", Some("world"), Some("!"))"#]]);
}
/// Helper function that is better than just `let _: ExpectedType = builder.get_foo();`
/// this notation involves an implicit deref coercion, but we want to assert the exact
/// return type of the getter without any additional implicit conversions.
fn assert_getter<'a, T, B>(builder: &'a B, method: fn(&'a B) -> T) -> T {
method(builder)
}
bon-3.7.1/tests/integration/builder/attr_into.rs 0000644 0000000 0000000 00000002735 10461020230 0020105 0 ustar 0000000 0000000 use crate::prelude::*;
use core::fmt;
use core::num::NonZeroU32;
#[cfg(feature = "alloc")]
#[test]
fn into_attr_alloc() {
use core::fmt;
#[builder]
fn sut(#[builder(into)] set: Option>, no_into: String) -> impl fmt::Debug {
(set, no_into)
}
assert_debug_eq(
sut().set([32, 43]).no_into("disabled".into()).call(),
expect![[r#"(Some({32, 43}), "disabled")"#]],
);
}
#[test]
fn into_attr_no_std() {
#[builder]
fn sut(
#[builder(into)] str_ref: &str,
/// Some docs
#[builder(into)]
u32: u32,
) -> impl fmt::Debug + '_ {
(str_ref, u32)
}
struct IntoStrRef<'a>(&'a str);
impl<'a> From> for &'a str {
fn from(val: IntoStrRef<'a>) -> Self {
val.0
}
}
assert_debug_eq(
sut()
.str_ref(IntoStrRef("vinyl-scratch"))
.u32(NonZeroU32::new(32).unwrap())
.call(),
expect![[r#"("vinyl-scratch", 32)"#]],
);
}
#[cfg(feature = "alloc")]
#[test]
fn into_string() {
#[builder(on(String, into))]
fn sut(arg1: String, arg2: Option) -> impl fmt::Debug {
(arg1, arg2)
}
assert_debug_eq(
sut().arg1("blackjack").arg2("bruh").call(),
expect![[r#"("blackjack", Some("bruh"))"#]],
);
assert_debug_eq(
sut().arg1("blackjack").maybe_arg2(Some("bruh2")).call(),
expect![[r#"("blackjack", Some("bruh2"))"#]],
);
}
bon-3.7.1/tests/integration/builder/attr_into_future.rs 0000644 0000000 0000000 00000017003 10461020230 0021471 0 ustar 0000000 0000000 /// [`core::future::IntoFuture`] relies on [`Box`]. Also this trait was
/// introduced in Rust 1.64, while `bon`'s MSRV is 1.59 at the time of this
/// writing.
#[cfg(any(feature = "std", feature = "alloc"))]
#[rustversion::since(1.64)]
mod tests {
use crate::prelude::*;
use core::future::{ready, IntoFuture};
use core::marker::PhantomData;
async fn assert_send(builder: B) -> B::Output
where
B: IntoFuture + Send,
B::IntoFuture: Send,
{
#[expect(clippy::incompatible_msrv)]
let fut = builder.into_future();
let _: &dyn Send = &fut;
fut.await
}
#[expect(clippy::future_not_send)]
async fn non_send_future() {
// By keeping `Rc` across an await point, we force the compiler to store it
// as part of the future's state machine struct and thus we make it non-Send
let non_send = PhantomData::>;
ready(()).await;
let _ = &non_send;
}
mod test_fn {
use super::*;
#[tokio::test]
async fn basic() {
#[builder(derive(IntoFuture(Box)))]
async fn simple_async_fn(value: u32) -> u32 {
ready(value * 2).await
}
// Test direct call.
let builder = simple_async_fn().value(21).call();
assert_eq!(assert_send(builder).await, 42);
// Test using IntoFuture with await.
let builder = simple_async_fn().value(21);
assert_eq!(assert_send(builder).await, 42);
}
#[tokio::test]
async fn non_send() {
#[builder(derive(IntoFuture(Box, ?Send)))]
#[expect(clippy::future_not_send)]
async fn non_send_async_fn(value: u32) -> u32 {
non_send_future().await;
// This future can be !Send.
ready(value * 2).await
}
// Test with non-Send future.
let result = non_send_async_fn().value(21).await;
assert_eq!(result, 42);
}
#[tokio::test]
async fn result() {
#[builder(derive(IntoFuture(Box)))]
async fn async_with_result(value: u32) -> Result {
ready(if value > 0 {
Ok(value * 2)
} else {
Err("Value must be positive")
})
.await
}
// Test successful case.
let builder = async_with_result().value(21);
assert_eq!(assert_send(builder).await.unwrap(), 42);
// Test error case.
let builder = async_with_result().value(0);
assert_send(builder).await.unwrap_err();
}
#[tokio::test]
async fn into_future_with_optional() {
#[builder(derive(IntoFuture(Box)))]
async fn optional_param(#[builder(default = 100)] value: u32) -> u32 {
ready(value).await
}
// Test with value.
let builder = optional_param().value(42);
assert_eq!(assert_send(builder).await, 42);
// Test without value (using default).
let builder = optional_param();
assert_eq!(assert_send(builder).await, 100);
}
#[tokio::test]
async fn references_in_params() {
struct Dummy;
#[builder(derive(IntoFuture(Box)))]
async fn sut<'named1, 'named2>(
_x1: &Dummy,
_x2: &Dummy,
x3: &'named1 Dummy,
x4: &'named2 Dummy,
) -> &'named2 Dummy {
let _: &'named1 Dummy = x3;
ready(x4).await
}
// Store the dummy struct in local variables to make sure no `'static`
// lifetime promotion happens
let local_x1 = Dummy;
let local_x2 = Dummy;
let local_x3 = Dummy;
let local_x4 = Dummy;
let builder = sut()
.x1(&local_x1)
.x2(&local_x2)
.x3(&local_x3)
.x4(&local_x4);
let &Dummy = assert_send(builder).await;
}
#[tokio::test]
async fn anon_lifetime_in_return_type() {
struct Dummy;
#[builder(derive(IntoFuture(Box)))]
async fn sut(x1: &Dummy) -> &Dummy {
ready(x1).await
}
// Store the dummy struct in local variables to make sure no `'static`
// lifetime promotion happens
let local_x1 = Dummy;
let builder = sut().x1(&local_x1);
let &Dummy = assert_send(builder).await;
}
}
mod test_method {
use super::*;
#[tokio::test]
async fn basic() {
struct Calculator;
#[bon]
impl Calculator {
#[builder]
#[builder(derive(IntoFuture(Box)))]
async fn multiply(a: u32, b: u32) -> u32 {
ready(a * b).await
}
}
// Test using IntoFuture on impl method.
let builder = Calculator::multiply().a(6).b(7);
assert_eq!(assert_send(builder).await, 42);
}
#[tokio::test]
async fn non_send() {
struct Sut;
#[bon]
impl Sut {
#[builder(derive(IntoFuture(Box, ?Send)))]
#[expect(clippy::future_not_send)]
async fn sut(self, value: u32) -> u32 {
non_send_future().await;
// This future can be !Send.
ready(value * 2).await
}
}
// Test with non-Send future.
let result = Sut.sut().value(21).await;
assert_eq!(result, 42);
}
#[tokio::test]
async fn references_in_params() {
struct Dummy;
#[bon]
impl Dummy {
#[builder(derive(IntoFuture(Box)))]
async fn sut<'named1, 'named2>(
&self,
_x1: &Self,
_x2: &Self,
x3: &'named1 Self,
x4: &'named2 Self,
) -> &'named2 Self {
let _: &'named1 Self = x3;
ready(x4).await
}
}
// Store the dummy struct in local variables to make sure no `'static`
// lifetime promotion happens
let local_self = Dummy;
let local_x1 = Dummy;
let local_x2 = Dummy;
let local_x3 = Dummy;
let local_x4 = Dummy;
let builder = local_self
.sut()
.x1(&local_x1)
.x2(&local_x2)
.x3(&local_x3)
.x4(&local_x4);
let _: &Dummy = assert_send(builder).await;
}
#[tokio::test]
async fn anon_lifetime_in_return_type() {
struct Dummy;
#[bon]
impl Dummy {
#[builder(derive(IntoFuture(Box)))]
async fn sut(&self, _x1: &Self) -> &Self {
ready(self).await
}
}
// Store the dummy struct in local variables to make sure no `'static`
// lifetime promotion happens
let local_self = Dummy;
let local_x1 = Dummy;
let builder = local_self.sut().x1(&local_x1);
let _: &Dummy = assert_send(builder).await;
}
}
}
bon-3.7.1/tests/integration/builder/attr_on.rs 0000644 0000000 0000000 00000002561 10461020230 0017545 0 ustar 0000000 0000000 use crate::prelude::*;
struct IntoBool(bool);
impl From for bool {
fn from(value: IntoBool) -> Self {
value.0
}
}
struct IntoUnit;
impl From for () {
fn from(IntoUnit: IntoUnit) {}
}
struct IntoStrRef<'a>(&'a str);
impl<'a> From> for &'a str {
fn from(value: IntoStrRef<'a>) -> Self {
value.0
}
}
struct Generic(T);
struct IntoGeneric(T);
impl From> for Generic {
fn from(value: IntoGeneric) -> Self {
Self(value.0)
}
}
#[test]
fn match_any() {
#[builder(on(_, into))]
fn sut(_arg1: bool, _arg2: Option<()>, _arg3: T) {}
sut::<&str>()
.arg1(IntoBool(true))
.arg2(IntoUnit)
.arg3(IntoStrRef("foo"))
.call();
}
#[test]
fn match_str_ref() {
#[builder(on(&str, into))]
fn sut(_arg1: bool, _arg2: Option<()>, _arg3: &str) {}
sut().arg1(true).arg2(()).arg3(IntoStrRef("foo")).call();
}
#[test]
fn match_path() {
#[builder(on(bool, into))]
fn sut(_arg1: bool, _arg2: Option<()>, _arg3: T) {}
sut::<&str>()
.arg1(IntoBool(true))
.arg2(())
.arg3("foo")
.call();
}
#[test]
fn match_generic() {
#[builder(on(Generic<_>, into))]
fn sut(_arg1: bool, _arg2: Option<()>, _arg3: Generic) {}
sut().arg1(true).arg2(()).arg3(IntoGeneric("foo")).call();
}
bon-3.7.1/tests/integration/builder/attr_overwritable.rs 0000644 0000000 0000000 00000004631 10461020230 0021636 0 ustar 0000000 0000000 mod smoke {
use crate::prelude::*;
use core::fmt;
#[test]
fn test_struct() {
#[derive(Debug, Builder)]
#[allow(dead_code)]
struct Sut {
#[builder(overwritable)]
a: u32,
#[builder(overwritable)]
b: Option,
#[builder(overwritable, default)]
c: u32,
}
assert_debug_eq(
Sut::builder().a(1).a(2).b(3).b(4).c(5).c(6).build(),
expect!["Sut { a: 2, b: Some(4), c: 6 }"],
);
}
#[test]
fn test_function() {
#[builder]
fn sut(
#[builder(overwritable)] a: u32,
#[builder(overwritable)] b: Option,
#[builder(overwritable, default)] c: u32,
) -> impl fmt::Debug {
(a, b, c)
}
assert_debug_eq(
sut().a(1).a(2).b(3).b(4).c(5).c(6).call(),
expect!["(2, Some(4), 6)"],
);
}
#[test]
fn test_method() {
struct Sut;
#[bon]
impl Sut {
#[builder]
fn sut(
#[builder(overwritable)] a: u32,
#[builder(overwritable)] b: Option,
#[builder(overwritable, default)] c: u32,
) -> impl fmt::Debug {
(a, b, c)
}
#[builder]
fn with_self(
&self,
#[builder(overwritable)] a: u32,
#[builder(overwritable)] b: Option,
#[builder(overwritable, default)] c: u32,
) -> impl fmt::Debug {
let _ = self;
(a, b, c)
}
}
assert_debug_eq(
Sut::sut().a(1).a(2).b(3).b(4).c(5).c(6).call(),
expect!["(2, Some(4), 6)"],
);
assert_debug_eq(
Sut.with_self().a(1).a(2).b(3).b(4).c(5).c(6).call(),
expect!["(2, Some(4), 6)"],
);
}
}
mod on {
use crate::prelude::*;
#[test]
fn test_struct() {
#[derive(Debug, Builder)]
#[allow(dead_code)]
#[builder(on(u32, overwritable))]
struct Sut {
a: u32,
b: Option,
#[builder(default)]
c: u32,
}
assert_debug_eq(
Sut::builder().a(1).a(2).b(3).b(4).c(5).c(6).build(),
expect!["Sut { a: 2, b: Some(4), c: 6 }"],
);
}
}
bon-3.7.1/tests/integration/builder/attr_required.rs 0000644 0000000 0000000 00000020662 10461020230 0020753 0 ustar 0000000 0000000 mod member_level {
use crate::prelude::*;
use core::fmt;
#[test]
fn test_struct() {
#[derive(Debug, Builder)]
#[allow(dead_code)]
struct Sut {
#[builder(required)]
regular: Option,
#[builder(required)]
generic: Option,
#[builder(required, into)]
with_into: Option,
#[builder(required, default = Some(99))]
with_default: Option,
#[builder(required, default = Some(10))]
with_default_2: Option,
}
assert_debug_eq(
Sut::builder()
.regular(Some(1))
.generic(Some(false))
.with_into(2)
.maybe_with_default_2(Some(Some(3)))
.build(),
expect![[r#"
Sut {
regular: Some(
1,
),
generic: Some(
false,
),
with_into: Some(
2,
),
with_default: Some(
99,
),
with_default_2: Some(
3,
),
}"#]],
);
}
#[test]
fn test_function() {
#[builder]
fn sut(
#[builder(required)] regular: Option,
#[builder(required)] generic: Option,
#[builder(required, into)] with_into: Option,
#[builder(required, default = Some(99))] with_default: Option,
#[builder(required, default = Some(10))] with_default_2: Option,
) -> impl fmt::Debug {
(regular, generic, with_into, with_default, with_default_2)
}
assert_debug_eq(
sut()
.regular(Some(1))
.generic(Some(false))
.with_into(2)
.maybe_with_default_2(Some(Some(3)))
.call(),
expect!["(Some(1), Some(false), Some(2), Some(99), Some(3))"],
);
}
#[test]
fn test_method() {
struct Sut;
#[bon]
impl Sut {
#[builder]
fn sut(
#[builder(required)] regular: Option,
#[builder(required)] generic: Option,
#[builder(required, into)] with_into: Option,
#[builder(required, default = Some(99))] with_default: Option,
#[builder(required, default = Some(10))] with_default_2: Option,
) -> impl fmt::Debug {
(regular, generic, with_into, with_default, with_default_2)
}
#[builder]
fn with_self(
&self,
#[builder(required)] regular: Option,
#[builder(required)] generic: Option,
#[builder(required, into)] with_into: Option,
#[builder(required, default = Some(99))] with_default: Option,
#[builder(required, default = Some(10))] with_default_2: Option,
) -> impl fmt::Debug {
let _ = self;
(regular, generic, with_into, with_default, with_default_2)
}
}
assert_debug_eq(
Sut::sut()
.regular(Some(1))
.generic(Some(false))
.with_into(2)
.maybe_with_default_2(Some(Some(3)))
.call(),
expect!["(Some(1), Some(false), Some(2), Some(99), Some(3))"],
);
assert_debug_eq(
Sut.with_self()
.regular(Some(1))
.generic(Some(false))
.with_into(2)
.maybe_with_default_2(Some(Some(3)))
.call(),
expect!["(Some(1), Some(false), Some(2), Some(99), Some(3))"],
);
}
}
mod attr_on {
use crate::prelude::*;
use core::fmt;
#[test]
fn test_struct() {
#[derive(Debug, Builder)]
#[builder(on(_, required))]
#[allow(dead_code)]
struct Sut {
#[builder(start_fn)]
start_fn: u32,
regular: Option,
generic: Option,
#[builder(into)]
with_into: Option,
#[builder(default = Some(99))]
with_default: Option,
#[builder(default = Some(10))]
with_default_2: Option,
}
assert_debug_eq(
Sut::builder(11)
.regular(Some(1))
.generic(Some(false))
.with_into(2)
.maybe_with_default_2(Some(Some(3)))
.build(),
expect![[r#"
Sut {
start_fn: 11,
regular: Some(
1,
),
generic: Some(
false,
),
with_into: Some(
2,
),
with_default: Some(
99,
),
with_default_2: Some(
3,
),
}"#]],
);
}
#[test]
fn test_function() {
#[builder(on(_, required))]
fn sut(
#[builder(start_fn)] start_fn: u32,
regular: Option,
generic: Option,
#[builder(into)] with_into: Option,
#[builder(default = Some(99))] with_default: Option,
#[builder(default = Some(10))] with_default_2: Option,
) -> impl fmt::Debug {
(
start_fn,
regular,
generic,
with_into,
with_default,
with_default_2,
)
}
assert_debug_eq(
sut(11)
.regular(Some(1))
.generic(Some(false))
.with_into(2)
.maybe_with_default_2(Some(Some(3)))
.call(),
expect!["(11, Some(1), Some(false), Some(2), Some(99), Some(3))"],
);
}
#[test]
fn test_method() {
struct Sut;
#[bon]
impl Sut {
#[builder(on(_, required))]
fn sut(
#[builder(start_fn)] start_fn: u32,
regular: Option,
generic: Option,
#[builder(into)] with_into: Option,
#[builder(default = Some(99))] with_default: Option,
#[builder(default = Some(10))] with_default_2: Option,
) -> impl fmt::Debug {
(
start_fn,
regular,
generic,
with_into,
with_default,
with_default_2,
)
}
#[builder(on(_, required))]
fn with_self(
&self,
#[builder(start_fn)] start_fn: u32,
regular: Option,
generic: Option,
#[builder(into)] with_into: Option,
#[builder(default = Some(99))] with_default: Option,
#[builder(default = Some(10))] with_default_2: Option,
) -> impl fmt::Debug {
let _ = self;
(
start_fn,
regular,
generic,
with_into,
with_default,
with_default_2,
)
}
}
assert_debug_eq(
Sut::sut(11)
.regular(Some(1))
.generic(Some(false))
.with_into(2)
.maybe_with_default_2(Some(Some(3)))
.call(),
expect!["(11, Some(1), Some(false), Some(2), Some(99), Some(3))"],
);
assert_debug_eq(
Sut.with_self(11)
.regular(Some(1))
.generic(Some(false))
.with_into(2)
.maybe_with_default_2(Some(Some(3)))
.call(),
expect!["(11, Some(1), Some(false), Some(2), Some(99), Some(3))"],
);
}
}
bon-3.7.1/tests/integration/builder/attr_setters.rs 0000644 0000000 0000000 00000032533 10461020230 0020624 0 ustar 0000000 0000000 mod name {
use crate::prelude::*;
#[test]
fn test_struct() {
#[derive(Builder)]
#[allow(dead_code)]
struct Sut {
#[builder(setters(name = arg1_renamed))]
arg1: bool,
#[builder(setters(name = arg2_renamed))]
arg2: Option<()>,
#[builder(setters(name = arg3_renamed), default)]
arg3: u32,
}
use sut_builder::*;
#[allow(type_alias_bounds)]
type _AssocTypes = (T::Arg1, T::Arg2, T::Arg3);
let _ = Sut::builder().arg1_renamed(true);
let _ = Sut::builder().arg2_renamed(());
let _ = Sut::builder().maybe_arg2_renamed(Some(()));
let _ = Sut::builder().arg3_renamed(42);
let _ = Sut::builder().maybe_arg3_renamed(Some(42));
// The name in the state must remain the same
let _: SutBuilder>> = Sut::builder()
.arg1_renamed(true)
.arg2_renamed(())
.arg3_renamed(42);
}
#[test]
fn test_function() {
#[builder]
fn sut(
#[builder(setters(name = arg1_renamed))] _arg1: bool,
#[builder(setters(name = arg2_renamed))] _arg2: Option<()>,
#[builder(setters(name = arg3_renamed), default)] _arg3: u32,
) {
}
use sut_builder::*;
#[allow(type_alias_bounds)]
type _AssocTypes = (T::Arg1, T::Arg2, T::Arg3);
let _ = sut().arg1_renamed(true);
let _ = sut().arg2_renamed(());
let _ = sut().maybe_arg2_renamed(Some(()));
let _ = sut().arg3_renamed(42);
let _ = sut().maybe_arg3_renamed(Some(42));
// The name in the state must remain the same
let _: SutBuilder>> =
sut().arg1_renamed(true).arg2_renamed(()).arg3_renamed(42);
}
#[test]
fn test_method() {
struct Sut;
#[bon]
impl Sut {
#[builder]
fn sut(
#[builder(setters(name = arg1_renamed))] _arg1: bool,
#[builder(setters(name = arg2_renamed))] _arg2: Option<()>,
#[builder(setters(name = arg3_renamed), default)] _arg3: u32,
) {
}
#[builder]
fn with_self(
&self,
#[builder(setters(name = arg1_renamed))] _arg1: bool,
#[builder(setters(name = arg2_renamed))] _arg2: Option<()>,
#[builder(setters(name = arg3_renamed), default)] _arg3: u32,
) {
let _ = self;
}
}
{
use sut_sut_builder::*;
#[allow(type_alias_bounds)]
type _AssocTypes = (T::Arg1, T::Arg2, T::Arg3);
let _ = Sut::sut().arg1_renamed(true);
let _ = Sut::sut().arg2_renamed(());
let _ = Sut::sut().maybe_arg2_renamed(Some(()));
let _ = Sut::sut().arg3_renamed(42);
let _ = Sut::sut().maybe_arg3_renamed(Some(42));
// The name in the state must remain the same
let _: SutSutBuilder>> = Sut::sut()
.arg1_renamed(true)
.arg2_renamed(())
.arg3_renamed(42);
}
{
use sut_with_self_builder::*;
#[allow(type_alias_bounds)]
type _AssocTypes = (T::Arg1, T::Arg2, T::Arg3);
let sut = Sut;
let _ = sut.with_self().arg1_renamed(true);
let _ = sut.with_self().arg2_renamed(());
let _ = sut.with_self().maybe_arg2_renamed(Some(()));
let _ = sut.with_self().arg3_renamed(42);
let _ = sut.with_self().maybe_arg3_renamed(Some(42));
// The name in the state must remain the same
let _: SutWithSelfBuilder<'_, SetArg3>> = sut
.with_self()
.arg1_renamed(true)
.arg2_renamed(())
.arg3_renamed(42);
}
}
}
mod option_fn_name_and_some_fn_name {
use crate::prelude::*;
#[test]
fn test_struct() {
#[derive(Builder)]
#[builder(derive(Clone))]
#[allow(dead_code)]
struct Sut {
#[builder(setters(some_fn = arg1_some))]
arg1: Option<()>,
#[builder(setters(option_fn = arg2_option))]
arg2: Option<()>,
#[builder(setters(some_fn = arg3_some, option_fn = arg3_option))]
arg3: Option<()>,
#[builder(setters(some_fn(name = arg4_some), option_fn(name = arg4_option)))]
arg4: Option<()>,
#[builder(default, setters(some_fn = arg5_some))]
arg5: (),
#[builder(default, setters(option_fn = arg6_option))]
arg6: (),
#[builder(default, setters(some_fn = arg7_some, option_fn = arg7_option))]
arg7: (),
#[builder(default, setters(some_fn(name = arg8_some), option_fn(name = arg8_option)))]
arg8: (),
}
use sut_builder::*;
let _ = Sut::builder().arg1_some(());
let _ = Sut::builder().maybe_arg1(Some(()));
let _ = Sut::builder().arg2(());
let _ = Sut::builder().arg2_option(Some(()));
let _ = Sut::builder().arg3_some(());
let _ = Sut::builder().arg3_option(Some(()));
let _ = Sut::builder().arg4_some(());
let _ = Sut::builder().arg4_option(Some(()));
let _ = Sut::builder().arg5_some(());
let _ = Sut::builder().maybe_arg5(Some(()));
let _ = Sut::builder().arg6(());
let _ = Sut::builder().arg6_option(Some(()));
let _ = Sut::builder().arg7_some(());
let _ = Sut::builder().arg7_option(Some(()));
let _ = Sut::builder().arg8_some(());
let _ = Sut::builder().arg8_option(Some(()));
#[allow(clippy::type_complexity)]
let _: SutBuilder<
SetArg8>>>>>>,
> = Sut::builder()
.arg1_some(())
.arg2(())
.arg3_some(())
.arg4_some(())
.arg5_some(())
.arg6(())
.arg7_some(())
.arg8_some(());
}
#[test]
fn test_function() {
#[builder(derive(Clone))]
fn sut(
#[builder(setters(some_fn = arg1_some))] _arg1: Option<()>,
#[builder(setters(option_fn = arg2_option))] _arg2: Option<()>,
#[builder(setters(some_fn = arg3_some, option_fn = arg3_option))] _arg3: Option<()>,
#[builder(setters(some_fn(name = arg4_some), option_fn(name = arg4_option)))]
_arg4: Option<()>,
#[builder(default, setters(some_fn = arg5_some))] _arg5: (),
#[builder(default, setters(option_fn = arg6_option))] _arg6: (),
#[builder(default, setters(some_fn = arg7_some, option_fn = arg7_option))] _arg7: (),
#[builder(default, setters(some_fn(name = arg8_some), option_fn(name = arg8_option)))]
_arg8: (),
) {
}
use sut_builder::*;
let _ = sut().arg1_some(());
let _ = sut().maybe_arg1(Some(()));
let _ = sut().arg2(());
let _ = sut().arg2_option(Some(()));
let _ = sut().arg3_some(());
let _ = sut().arg3_option(Some(()));
let _ = sut().arg4_some(());
let _ = sut().arg4_option(Some(()));
let _ = sut().arg5_some(());
let _ = sut().maybe_arg5(Some(()));
let _ = sut().arg6(());
let _ = sut().arg6_option(Some(()));
let _ = sut().arg7_some(());
let _ = sut().arg7_option(Some(()));
let _ = sut().arg8_some(());
let _ = sut().arg8_option(Some(()));
#[allow(clippy::type_complexity)]
let _: SutBuilder<
SetArg8>>>>>>,
> = sut()
.arg1_some(())
.arg2(())
.arg3_some(())
.arg4_some(())
.arg5_some(())
.arg6(())
.arg7_some(())
.arg8_some(());
}
#[test]
fn test_method() {
struct Sut;
#[bon]
impl Sut {
#[builder(derive(Clone))]
fn sut(
#[builder(setters(some_fn = arg1_some))] _arg1: Option<()>,
#[builder(setters(option_fn = arg2_option))] _arg2: Option<()>,
#[builder(setters(some_fn = arg3_some, option_fn = arg3_option))] _arg3: Option<()>,
#[builder(setters(some_fn(name = arg4_some), option_fn(name = arg4_option)))]
_arg4: Option<()>,
#[builder(default, setters(some_fn = arg5_some))] _arg5: (),
#[builder(default, setters(option_fn = arg6_option))] _arg6: (),
#[builder(default, setters(some_fn = arg7_some, option_fn = arg7_option))] _arg7: (
),
#[builder(default, setters(some_fn(name = arg8_some), option_fn(name = arg8_option)))]
_arg8: (),
) {
}
#[builder(derive(Clone))]
fn with_self(
&self,
#[builder(setters(some_fn = arg1_some))] _arg1: Option<()>,
#[builder(setters(option_fn = arg2_option))] _arg2: Option<()>,
#[builder(setters(some_fn = arg3_some, option_fn = arg3_option))] _arg3: Option<()>,
#[builder(setters(some_fn(name = arg4_some), option_fn(name = arg4_option)))]
_arg4: Option<()>,
#[builder(default, setters(some_fn = arg5_some))] _arg5: (),
#[builder(default, setters(option_fn = arg6_option))] _arg6: (),
#[builder(default, setters(some_fn = arg7_some, option_fn = arg7_option))] _arg7: (
),
#[builder(default, setters(some_fn(name = arg8_some), option_fn(name = arg8_option)))]
_arg8: (),
) {
let _ = self;
}
}
{
use sut_sut_builder::*;
let _ = Sut::sut().arg1_some(());
let _ = Sut::sut().maybe_arg1(Some(()));
let _ = Sut::sut().arg2(());
let _ = Sut::sut().arg2_option(Some(()));
let _ = Sut::sut().arg3_some(());
let _ = Sut::sut().arg3_option(Some(()));
let _ = Sut::sut().arg4_some(());
let _ = Sut::sut().arg4_option(Some(()));
let _ = Sut::sut().arg5_some(());
let _ = Sut::sut().maybe_arg5(Some(()));
let _ = Sut::sut().arg6(());
let _ = Sut::sut().arg6_option(Some(()));
let _ = Sut::sut().arg7_some(());
let _ = Sut::sut().arg7_option(Some(()));
let _ = Sut::sut().arg8_some(());
let _ = Sut::sut().arg8_option(Some(()));
#[allow(clippy::type_complexity)]
let _: SutSutBuilder<
SetArg8>>>>>>,
> = Sut::sut()
.arg1_some(())
.arg2(())
.arg3_some(())
.arg4_some(())
.arg5_some(())
.arg6(())
.arg7_some(())
.arg8_some(());
}
{
use sut_with_self_builder::*;
let _ = Sut.with_self().arg1_some(());
let _ = Sut.with_self().maybe_arg1(Some(()));
let _ = Sut.with_self().arg2(());
let _ = Sut.with_self().arg2_option(Some(()));
let _ = Sut.with_self().arg3_some(());
let _ = Sut.with_self().arg3_option(Some(()));
let _ = Sut.with_self().arg4_some(());
let _ = Sut.with_self().arg4_option(Some(()));
let _ = Sut.with_self().arg5_some(());
let _ = Sut.with_self().maybe_arg5(Some(()));
let _ = Sut.with_self().arg6(());
let _ = Sut.with_self().arg6_option(Some(()));
let _ = Sut.with_self().arg7_some(());
let _ = Sut.with_self().arg7_option(Some(()));
let _ = Sut.with_self().arg8_some(());
let _ = Sut.with_self().arg8_option(Some(()));
#[allow(clippy::type_complexity)]
let _: SutWithSelfBuilder<
'_,
SetArg8>>>>>>,
> = Sut
.with_self()
.arg1_some(())
.arg2(())
.arg3_some(())
.arg4_some(())
.arg5_some(())
.arg6(())
.arg7_some(())
.arg8_some(());
}
}
}
mod self_references_in_docs {
use crate::prelude::*;
#[test]
fn test_struct() {
/// [`Self`] link
#[derive(Builder)]
struct Sut {
/// [`Self`] link
#[builder(setters(doc {}))]
_arg1: u32,
/// [`Self`] link
#[builder(setters(
option_fn(doc {}),
some_fn(doc {})
))]
_arg2: Option,
}
let _ = Sut::builder().arg1(42);
}
#[test]
fn test_function() {
/// [`Self`] link
#[builder]
fn sut(
/// [`Self`] link
#[builder(setters(doc {}))]
_arg1: u32,
) {
}
let _ = sut().arg1(42);
}
}
bon-3.7.1/tests/integration/builder/attr_skip.rs 0000644 0000000 0000000 00000005150 10461020230 0020074 0 ustar 0000000 0000000 use crate::prelude::*;
use expect_test::expect;
#[cfg(feature = "alloc")]
#[test]
fn struct_alloc() {
use expect_test::expect;
#[derive(Debug, Builder)]
struct Sut {
#[builder(skip = "skip".to_owned())]
#[allow(dead_code)]
arg1: String,
#[builder(skip = vec![42])]
#[allow(dead_code)]
arg2: Vec,
}
assert_debug_eq(
Sut::builder().build(),
expect![[r#"Sut { arg1: "skip", arg2: [42] }"#]],
);
}
#[test]
fn struct_no_std() {
#[derive(Debug, Builder)]
struct Sut {
#[builder(skip)]
#[allow(dead_code)]
arg1: u32,
#[builder(skip = 42)]
#[allow(dead_code)]
arg2: u32,
}
assert_debug_eq(Sut::builder().build(), expect!["Sut { arg1: 0, arg2: 42 }"]);
}
#[test]
fn struct_with_non_skipped_arg() {
#[derive(Debug, Builder)]
struct Sut {
#[builder(skip)]
#[allow(dead_code)]
arg1: u32,
#[allow(dead_code)]
arg2: u32,
}
assert_debug_eq(
Sut::builder().arg2(24).build(),
expect!["Sut { arg1: 0, arg2: 24 }"],
);
}
#[test]
fn struct_generic_skipped() {
#[derive(Builder)]
struct Sut
where
A: Clone + Default,
B: Clone + Default,
{
#[builder(skip)]
#[allow(dead_code)]
arg1: A,
#[builder(skip = <_>::default())]
#[allow(dead_code)]
arg2: B,
}
let _: Sut<(), ()> = Sut::<(), ()>::builder().build();
}
#[test]
fn interaction_with_positional_members() {
#[derive(Builder, Debug)]
#[allow(dead_code)]
struct Sut {
#[builder(start_fn)]
starter_1: u32,
#[builder(start_fn)]
starter_2: u32,
#[builder(finish_fn)]
finisher_1: u32,
#[builder(finish_fn)]
finisher_2: u32,
#[builder(skip = [starter_1, starter_2, finisher_1, finisher_2])]
named_1: [u32; 4],
#[builder(skip = (32, named_1))]
named_2: (u32, [u32; 4]),
}
assert_debug_eq(
Sut::builder(1, 2).build(3, 4),
expect![[r#"
Sut {
starter_1: 1,
starter_2: 2,
finisher_1: 3,
finisher_2: 4,
named_1: [
1,
2,
3,
4,
],
named_2: (
32,
[
1,
2,
3,
4,
],
),
}"#]],
);
}
bon-3.7.1/tests/integration/builder/attr_top_level_start_fn.rs 0000644 0000000 0000000 00000003657 10461020230 0023031 0 ustar 0000000 0000000 use crate::prelude::*;
use core::fmt;
#[test]
fn test_method() {
{
struct Sut;
#[bon]
impl Sut {
#[builder(start_fn = builder)]
fn new() -> Self {
Self
}
#[builder(start_fn = regular_builder)]
fn regular() {}
}
let builder: SutBuilder = Sut::builder();
let _: Sut = builder.build();
let _: Sut = Sut::new();
Sut::regular_builder().call();
Sut::regular();
}
{
pub(crate) struct Sut;
#[bon]
impl Sut {
#[builder(start_fn(name = builder, vis = ""))]
pub(crate) fn new() -> Self {
Self
}
#[builder(start_fn(name = regular_builder, vis = ""))]
pub(crate) fn regular() {}
}
let builder: SutBuilder = Sut::builder();
let _: Sut = builder.build();
let _: Sut = Sut::new();
Sut::regular_builder().call();
Sut::regular();
}
}
#[test]
fn test_function() {
{
#[builder(start_fn(name = sut_builder))]
fn sut(arg1: bool, arg2: u32) -> impl fmt::Debug {
(arg1, arg2)
}
assert_debug_eq(sut(true, 42), expect!["(true, 42)"]);
}
{
#[builder(start_fn = sut_builder)]
fn sut(arg1: u32) -> u32 {
arg1
}
assert_debug_eq(sut(42), expect!["42"]);
}
{
#[builder(start_fn(name = sut_builder, vis = ""))]
fn sut(arg1: u32) -> u32 {
arg1
}
assert_debug_eq(sut(42), expect!["42"]);
}
{
/// Docs on `sut`
#[builder(start_fn(name = sut_builder, doc {
/// Docs on `sut_builder`
}))]
fn sut(arg1: u32) -> u32 {
arg1
}
assert_debug_eq(sut_builder().arg1(42).call(), expect!["42"]);
assert_debug_eq(sut(42), expect!["42"]);
}
}
bon-3.7.1/tests/integration/builder/attr_with/from_iter.rs 0000644 0000000 0000000 00000031306 10461020230 0022071 0 ustar 0000000 0000000 #![cfg(feature = "std")]
#![allow(clippy::linkedlist)]
use crate::prelude::*;
use core::fmt;
use std::collections::{BinaryHeap, HashMap, HashSet, VecDeque};
type RenamedVec = Vec;
#[test]
fn test_struct() {
#[derive(Debug, Builder)]
#[builder(derive(Clone))]
struct Sut {
#[builder(with = <_>::from_iter)]
_vec: Vec,
#[builder(with = FromIterator::from_iter)]
_optional_vec: Option<::alloc::vec::Vec>,
#[builder(with = <_>::from_iter, default)]
_default_vec: Vec,
#[builder(with = FromIterator::from_iter)]
_renamed_vec: RenamedVec,
#[builder(with = <_>::from_iter)]
_hash_set: HashSet,
#[builder(with = FromIterator::from_iter)]
_btree_set: BTreeSet,
#[builder(with = <_>::from_iter)]
_vec_deque: VecDeque,
#[builder(with = FromIterator::from_iter)]
_binary_heap: BinaryHeap,
#[builder(with = <_>::from_iter)]
_linked_list: std::collections::LinkedList,
#[builder(with = FromIterator::from_iter)]
_hash_map: HashMap,
#[builder(with = <_>::from_iter)]
_btree_map: std::collections::BTreeMap,
}
let builder = Sut::builder();
let _ignore = builder.clone().optional_vec([1, 2, 3]);
let builder = builder.maybe_optional_vec(Some([4, 5, 6]));
let _ignore = builder.clone().default_vec([7, 8, 9]);
let builder = builder.maybe_default_vec(Some([10, 11, 12]));
// `Hash*`` collections have random order of iteration, so their debug
// output is unstable. To work around this instability, we just specify
// a single element for `Hash*` collections.
let sut = builder
.vec([13, 14, 15])
.renamed_vec([16, 17, 18])
.hash_set(std::iter::once(19))
.btree_set([20, 21, 22, 22, 21])
.vec_deque([23, 24, 25])
.binary_heap([26, 27, 28])
.linked_list([29, 30, 31])
.hash_map(std::iter::once((32, 33)))
.btree_map([(34, 35), (34, 36), (37, 38)])
.build();
assert_debug_eq(
&sut,
expect![[r#"
Sut {
_vec: [
13,
14,
15,
],
_optional_vec: Some(
[
4,
5,
6,
],
),
_default_vec: [
10,
11,
12,
],
_renamed_vec: [
16,
17,
18,
],
_hash_set: {
19,
},
_btree_set: {
20,
21,
22,
},
_vec_deque: [
23,
24,
25,
],
_binary_heap: [
28,
27,
26,
],
_linked_list: [
29,
30,
31,
],
_hash_map: {
32: 33,
},
_btree_map: {
34: 36,
37: 38,
},
}"#]],
);
}
#[test]
fn test_function() {
#[builder(derive(Clone))]
fn sut(
#[builder(with = <_>::from_iter)] vec: Vec,
#[builder(with = FromIterator::from_iter)] optional_vec: Option<::alloc::vec::Vec>,
#[builder(with = <_>::from_iter, default)] default_vec: Vec,
#[builder(with = FromIterator::from_iter)] renamed_vec: RenamedVec,
#[builder(with = <_>::from_iter)] hash_set: HashSet,
#[builder(with = FromIterator::from_iter)] btree_set: BTreeSet,
#[builder(with = <_>::from_iter)] vec_deque: VecDeque