derive_builder-0.12.0/.cargo_vcs_info.json0000644000000001540000000000100141000ustar { "git": { "sha1": "5705f00f23e3bd77c453a1c0bbd3de34b572b049" }, "path_in_vcs": "derive_builder" }derive_builder-0.12.0/CHANGELOG.md000064400000000000000000000234311046102023000145040ustar 00000000000000# Change Log All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). ## [0.12.0] - 2022-11-28 - Produce error when `default` is used with `field(type = "...")` rather than silently ignoring `default` #269 - Add support for `crate = "..."` to support re-export scenarios #274 ## [0.11.2] - 2022-04-20 - Allow restricted visibility using `vis = "..."` for builders, build methods, setters, and fields #247 - Allow specifying the type of a builder field using `#[builder(field(type = "..."))]` #246 - Allow specifying how a builder field is built using `#[builder(field(build = "..."))]` #246 - Update `darling`, `proc-macro2`, `syn`, and `quote` dependencies #250 ## [0.11.1] - 2022-03-16 - Forward `allow` and `cfg` attributes from the deriving struct to the builder and its impl block #222 - Support passing attributes to the builder struct using `#[builder_struct_attr(...)]` - Support passing attributes to the builder struct's inherent `impl` block using `#[builder_impl_attr(...)]` ## [0.11.0] - 2022-03-15 - Support shorthand and long-form collection setters; `#[builder(setter(each = "..."))]` and `#[builder(setter(each(name = "...")))]` #234 - Allow collection setters to be generic over `Into` using `#[builder(setter(each(name = "...", into)))] #234 and #214 - Allow specifying attributes for builder fields and setters using `#[builder_field_attr(...)]` and `#[builder_setter_attr(...)]` #237 ## [0.10.2] - 2021-04-21 - Don't reference `derive_builder_core` from `derive_builder` #206 ## [0.10.1] - 2021-04-20 - Don't reference `std` in no_std contexts #204 ## [0.10.0] - 2021-03-31 - Requires Rust 1.40.0 or newer (was 1.37.0) #169 - Logging feature is removed #177 - Type parameters no longer have the `Default` bound #178 - Make most of `derive_builder_core` private #189 - Add `setter(each = "name")` for extension of collection-like fields #199 ## [0.10.0-alpha] - 2021-01-13 - Requires Rust 1.40.0 or newer (was 1.37.0) #169 - Logging feature is removed #177 - Type parameters no longer have the `Default` bound #178 - Make most of `derive_builder_core` private #189 ## [0.9.0] - 2019-11-07 - Add `setter(custom)` to allow implementing a custom setter #154 ## [0.8.1] - 2019-10-30 - Increase `darling` dependency to 0.10.2 #153 ## [0.8.0] - 2019-09-30 - Increase dependency versions to latest #148 - Requires Rust 1.37.0 or newer (was 1.18.0) #148 - Increase version of derive_builder_core crate to match crate's public interface ## [0.7.2] - 2019-05-22 - Add `strip_option` flag for setter #116 ## [0.7.1] - 2019-02-05 - Updated `darling` to `0.8.5` and switched to better errors ## [0.7.0] - 2018-10-22 ### Breaking Changes - Updated all dependencies to latest versions #138 ## [0.6.0] - 2018-09-04 ### Breaking Changes - Requires Rust 1.18.0 or newer (was 1.15.0) #120 - Updated to `syn` 0.13.10. #120 - Updated to `quote` 0.5.2 #120 - Removed support for deprecated attributes #120 ### Changed - `Clone` is no longer derived on a builder using the owned pattern unless it has a field override that uses the mutable/immutable pattern. #97 - Using `#[builder(private)]` at the struct level will now emit a private builder. #99 ### Added - Use `build_fn(private)` to generate a build method only accessible within the mod scope #89 ### Internal Changes - Rewrote options parser using `darling` 0.6.3 #120 ## [0.5.2] - 2018-05-31 ### Fixed - Generated code for structs with type parameters and struct-level defaults now compiles #127 ## [0.5.1] - 2017-12-16 ### Changed - The standard library `collections` crate was merged into `alloc` ([PR](https://github.com/rust-lang/rust/pull/42648)). Correspondingly when using this crate within a crate with `#![no_std]` you must use `#![feature(alloc)] extern crate alloc` in your crate, was `#![feature(collections)] extern crate collections`. ### Fixed - `unused_mut` lint (variable does not need to be mutable) #104 ## [0.5.0] - 2017-06-30 ### Changed - `#[builder(default)]` and `#[builder(default = "...")]` at the struct level change their behaviour and construct a default value for the struct, instead of all fields individually. - builder fields are no longer public by default; Fields can be explicitly made public at the struct or field level using the new attribute: `#[builder(field(public))]` ### Removed - removed previously deprecated syntax `#[builder(setter_prefix = "with")]`, please use `#[builder(setter(prefix = "with"))]` instead ## [0.4.7] - 2017-04-29 ### Fixed - for generic structs, apply the `T: Clone` type bound in builder impl instead of struct definition #91 - only emit the `T: Clone` type bound when it is actually needed, i.e. mutable/immutable pattern, but not owned pattern. ## [0.4.6] - 2017-04-26 ### Added - pre-build validation via `#[builder(build_fn(validate = "path::to::fn"))]` ## [0.4.5] - 2017-04-25 ### Added - customize setter names via `#[builder(setter(name = "..."))]` - customize build_fn name via `#[builder(build_fn(name = "..."))]` - suppress build method generation via `#[builder(build_fn(skip))]` - derive additional traits via `#[builder(derive(Trait1, Trait2, ...))]` - set field visibility separate from setter visibility via `#[builder(field(private))]` at the field or struct level ### Deprecated - builder fields will no longer be public by default in 0.5.0; relying on this will now emit a deprecation warning. Fields can be explicitly made public at the struct or field level using the new `#[builder(field(public))]` attribute. To squelch this warning and opt-into the new behaviour, use the `private_fields` crate feature or explicitly set field visibility at the struct level. ## [0.4.4] - 2017-04-12 ### Added - try_setters, e.g. `#[builder(try_setter)]`. These setters are exposed alongside the normal field setters and allow callers to pass in values which have fallible conversions to the needed type through `TryInto`. This attribute can only be used on nightly when `#![feature(try_from)]` is declared in the consuming crate's root; this will change when Rust issue [#33417](https://github.com/rust-lang/rust/issues/33417) is resolved. ## [0.4.3] - 2017-04-11 ### Fixed - `setter(skip)` honors struct-inherited and explicit defaults #68 ## [0.4.2] - 2017-04-10 ### Fixed - support generic references in structs #55 - support `#![no_std]` #63 ## [0.4.1] - 2017-04-08 ### Deprecated - `#[builder(default)]` and `#[builder(default = "...")]` at the struct level will change their behaviour in 0.5.0 and construct a default value for the struct, instead of all fields individually. To opt into the new behaviour and squelch this deprecation warning you can add the `struct_default` feature flag. ## [0.4.0] - 2017-03-25 ### Added - skip setters, e.g. `#[builder(setter(skip))]` - default values, e.g. `#[builder(default = "42")]` or just `#[builder(default)]` ### Changed - deprecated syntax `#[builder(setter_prefix = "with")]`, please use `#[builder(setter(prefix = "with"))]` instead - setter conversions are now off by default, you can opt-into via `#[builder(setter(into))]` - logging is behind a feature flag. To activate it, please add `features = ["logging"]` to the dependency in `Cargo.toml`. Then you can use it like: `RUST_LOG=derive_builder=trace cargo test`. ### Fixed - use full path for result #39 - support `#[deny(missing_docs)]` #37 - support `#![no_std]` via `#[builder(no_std)]` #41 ## [0.3.0] - 2017-02-05 Requires Rust 1.15 or newer. ### Added - different setter pattern, e.g. `#[builder(pattern = "immutable")]` - private setters, e.g. `#[builder(private)]` - additional debug info via env_logger, e.g. `RUST_LOG=derive_builder=trace cargo test` - prefixes, e.g. `#[builder(setter_prefix = "with")]` - field specific overrides - customize builder name, e.g. `#[builder(name = "MyBuilder")]` ### Changed - migration to macros 1.1 - migration to traditional builder pattern i.e. seperate `FooBuilder` struct to build `Foo` => please refer to the new docs ### Fixed - missing lifetime support #21 ## [0.2.1] - 2016-09-24 ### Fixed - preserve ordering of attributes #27 ## [0.2.0] - 2016-08-22 ### Added - struct fields can be public - struct fields can have attributes - the following struct-attributes are copied to the setter-method - `/// ...` - `#[doc = ...]` - `#[cfg(...)]` - `#[allow(...)]` ### Changed - setter-methods are non-consuming now -- breaking change - setter-methods are public now ### Fixed - automatic documentation does not work #16 ## [0.1.0] - 2016-08-07 ### Added - first implementation - generate setter methods - support for generic structs [Unreleased]: https://github.com/colin-kiegel/rust-derive-builder/compare/v0.5.1...HEAD [0.5.1]: https://github.com/colin-kiegel/rust-derive-builder/compare/v0.5.0...v0.5.1 [0.5.0]: https://github.com/colin-kiegel/rust-derive-builder/compare/v0.4.7...v0.5.0 [0.4.7]: https://github.com/colin-kiegel/rust-derive-builder/compare/v0.4.6...v0.4.7 [0.4.6]: https://github.com/colin-kiegel/rust-derive-builder/compare/v0.4.5...v0.4.6 [0.4.5]: https://github.com/colin-kiegel/rust-derive-builder/compare/v0.4.4...v0.4.5 [0.4.4]: https://github.com/colin-kiegel/rust-derive-builder/compare/v0.4.3...v0.4.4 [0.4.3]: https://github.com/colin-kiegel/rust-derive-builder/compare/v0.4.2...v0.4.3 [0.4.2]: https://github.com/colin-kiegel/rust-derive-builder/compare/v0.4.1...v0.4.2 [0.4.1]: https://github.com/colin-kiegel/rust-derive-builder/compare/v0.4.0...v0.4.1 [0.4.0]: https://github.com/colin-kiegel/rust-derive-builder/compare/v0.3.0...v0.4.0 [0.3.0]: https://github.com/colin-kiegel/rust-derive-builder/compare/v0.2.1...v0.3.0 [0.2.1]: https://github.com/colin-kiegel/rust-derive-builder/compare/v0.2.0...v0.2.1 [0.2.0]: https://github.com/colin-kiegel/rust-derive-builder/compare/v0.1.0...v0.2.0 [0.1.0]: https://github.com/colin-kiegel/rust-derive-builder/tree/v0.1.0 derive_builder-0.12.0/Cargo.lock0000644000000165730000000000100120670ustar # This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 3 [[package]] name = "ansi_term" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" dependencies = [ "winapi", ] [[package]] name = "ctor" version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096" dependencies = [ "quote", "syn", ] [[package]] name = "darling" version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b0dd3cd20dc6b5a876612a6e5accfe7f3dd883db6d07acfbf14c128f61550dfa" dependencies = [ "darling_core", "darling_macro", ] [[package]] name = "darling_core" version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a784d2ccaf7c98501746bf0be29b2022ba41fd62a2e622af997a03e9f972859f" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", "strsim", "syn", ] [[package]] name = "darling_macro" version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7618812407e9402654622dd402b0a89dff9ba93badd6540781526117b92aab7e" dependencies = [ "darling_core", "quote", "syn", ] [[package]] name = "derive_builder" version = "0.12.0" dependencies = [ "derive_builder_macro", "pretty_assertions", "rustversion", "serde", "serde_json", "trybuild", ] [[package]] name = "derive_builder_core" version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c11bdc11a0c47bc7d37d582b5285da6849c96681023680b906673c5707af7b0f" dependencies = [ "darling", "proc-macro2", "quote", "syn", ] [[package]] name = "derive_builder_macro" version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebcda35c7a396850a55ffeac740804b40ffec779b98fffbb1738f4033f0ee79e" dependencies = [ "derive_builder_core", "syn", ] [[package]] name = "difference" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" [[package]] name = "fnv" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "glob" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" [[package]] name = "ident_case" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "itoa" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc" [[package]] name = "once_cell" version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860" [[package]] name = "output_vt100" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "628223faebab4e3e40667ee0b2336d34a5b960ff60ea743ddfdbcf7770bcfb66" dependencies = [ "winapi", ] [[package]] name = "pretty_assertions" version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f81e1644e1b54f5a68959a29aa86cde704219254669da328ecfdf6a1f09d427" dependencies = [ "ansi_term", "ctor", "difference", "output_vt100", ] [[package]] name = "proc-macro2" version = "1.0.47" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" dependencies = [ "unicode-ident", ] [[package]] name = "quote" version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" dependencies = [ "proc-macro2", ] [[package]] name = "rustversion" version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97477e48b4cf8603ad5f7aaf897467cf42ab4218a38ef76fb14c2d6773a6d6a8" [[package]] name = "ryu" version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" [[package]] name = "serde" version = "1.0.148" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e53f64bb4ba0191d6d0676e1b141ca55047d83b74f5607e6d8eb88126c52c2dc" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" version = "1.0.148" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a55492425aa53521babf6137309e7d34c20bbfbbfcfe2c7f3a047fd1f6b92c0c" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "serde_json" version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "020ff22c755c2ed3f8cf162dbb41a7268d934702f3ed3631656ea597e08fc3db" dependencies = [ "itoa", "ryu", "serde", ] [[package]] name = "strsim" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "syn" version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ae548ec36cf198c0ef7710d3c230987c2d6d7bd98ad6edc0274462724c585ce" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] [[package]] name = "termcolor" version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" dependencies = [ "winapi-util", ] [[package]] name = "toml" version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7" dependencies = [ "serde", ] [[package]] name = "trybuild" version = "1.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db29f438342820400f2d9acfec0d363e987a38b2950bdb50a7069ed17b2148ee" dependencies = [ "glob", "once_cell", "serde", "serde_derive", "serde_json", "termcolor", "toml", ] [[package]] name = "unicode-ident" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" [[package]] name = "winapi" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" dependencies = [ "winapi-i686-pc-windows-gnu", "winapi-x86_64-pc-windows-gnu", ] [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" dependencies = [ "winapi", ] [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" derive_builder-0.12.0/Cargo.toml0000644000000030100000000000100120700ustar # 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] name = "derive_builder" version = "0.12.0" authors = [ "Colin Kiegel ", "Pascal Hertleif ", "Jan-Erik Rediger ", "Ted Driggs ", ] description = "Rust macro to automatically implement the builder pattern for arbitrary structs." documentation = "https://docs.rs/derive_builder/0.12.0" readme = "README.md" keywords = [ "derive", "macro", "builder", "setter", "struct", ] categories = [ "development-tools", "rust-patterns", ] license = "MIT/Apache-2.0" repository = "https://github.com/colin-kiegel/rust-derive-builder" [dependencies.derive_builder_macro] version = "=0.12.0" [dev-dependencies.pretty_assertions] version = "0.6.1" [dev-dependencies.rustversion] version = "1.0.4" [dev-dependencies.serde] version = "1" features = ["derive"] [dev-dependencies.serde_json] version = "1" [features] clippy = ["derive_builder_macro/clippy"] default = ["std"] std = [] [target."cfg(compiletests)".dev-dependencies.trybuild] version = "1.0.38" derive_builder-0.12.0/Cargo.toml.orig000064400000000000000000000017651046102023000155700ustar 00000000000000[package] name = "derive_builder" version = "0.12.0" authors = ["Colin Kiegel ", "Pascal Hertleif ", "Jan-Erik Rediger ", "Ted Driggs "] description = "Rust macro to automatically implement the builder pattern for arbitrary structs." repository = "https://github.com/colin-kiegel/rust-derive-builder" documentation = "https://docs.rs/derive_builder/0.12.0" license = "MIT/Apache-2.0" categories = ["development-tools", "rust-patterns"] keywords = ["derive", "macro", "builder", "setter", "struct"] readme = "README.md" [features] default = ["std"] std = [] clippy = ["derive_builder_macro/clippy"] [dependencies] derive_builder_macro = { version = "=0.12.0", path = "../derive_builder_macro" } [dev-dependencies] pretty_assertions = "0.6.1" rustversion = "1.0.4" serde = { version = "1", features = ["derive"] } serde_json = "1" [target.'cfg(compiletests)'.dev-dependencies] trybuild = "1.0.38"derive_builder-0.12.0/LICENSE-APACHE000064400000000000000000000261361046102023000146240ustar 00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "{}" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright {yyyy} {name of copyright owner} Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. derive_builder-0.12.0/LICENSE-MIT000064400000000000000000000021131046102023000143210ustar 00000000000000The MIT License (MIT) Copyright (c) 2016 rust-derive-builder contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. derive_builder-0.12.0/README.md000064400000000000000000000204511046102023000141510ustar 00000000000000![Build](https://github.com/colin-kiegel/rust-derive-builder/workflows/Build/badge.svg) [![Rust version](https://img.shields.io/badge/rust-1.40+-blue.svg)]() [![Documentation](https://docs.rs/derive_builder/badge.svg)](https://docs.rs/derive_builder) [![Latest version](https://img.shields.io/crates/v/derive_builder.svg)](https://crates.io/crates/derive_builder) [![All downloads](https://img.shields.io/crates/d/derive_builder.svg)](https://crates.io/crates/derive_builder) [![Downloads of latest version](https://img.shields.io/crates/dv/derive_builder.svg)](https://crates.io/crates/derive_builder) # Builder Pattern Derive [Rust][rust] macro to automatically implement the **builder pattern** for arbitrary structs. A simple `#[derive(Builder)]` will generate a `FooBuilder` for your struct `Foo` with all setter-methods and a build method. ## How it Works ```rust #[macro_use] extern crate derive_builder; #[derive(Default, Builder, Debug)] #[builder(setter(into))] struct Channel { token: i32, special_info: i32, // .. a whole bunch of other fields .. } fn main() { // builder pattern, go, go, go!... let ch = ChannelBuilder::default() .special_info(42u8) .token(19124) .build() .unwrap(); println!("{:?}", ch); } ``` Note that we did not write any definition or implementation of `ChannelBuilder`. Instead the `derive_builder` crate acts on `#[derive(Builder)]` and generates the necessary code at compile time. This is the generated boilerplate code you didn't need to write. :-) ```rust,ignore #[derive(Clone, Default)] struct ChannelBuilder { token: Option, special_info: Option, } #[allow(dead_code)] impl ChannelBuilder { pub fn token>(&mut self, value: VALUE) -> &mut Self { let mut new = self; new.token = Some(value.into()); new } pub fn special_info>(&mut self, value: VALUE) -> &mut Self { let mut new = self; new.special_info = Some(value.into()); new } fn build( &self, ) -> Result { Ok(Channel { id: match self.id { Some(ref value) => Clone::clone(value), None => { return Err( Into::into( ::derive_builder::UninitializedFieldError::from("id"), ), ) } }, token: match self.token { Some(ref value) => Clone::clone(value), None => { return Err( Into::into( ::derive_builder::UninitializedFieldError::from("token"), ), ) } }, special_info: match self.special_info { Some(ref value) => Clone::clone(value), None => { return Err( Into::into( ::derive_builder::UninitializedFieldError::from("special_info"), ), ) } }, }) } } ``` _Note: This is edited for readability. The generated code doesn't assume traits such as `Into` are in-scope, and uses full paths to access them._ ## Get Started It's as simple as three steps: 1. Add `derive_builder` to your `Cargo.toml` either manually or with [cargo-edit](https://github.com/killercup/cargo-edit): - `cargo add derive_builder` 2. Add `use derive_builder::Builder;` 3. Annotate your struct with `#[derive(Builder)]` ## Usage and Features - **Chaining**: The setter calls can be chained, because they consume and return `&mut self` by default. - **Builder patterns**: You can opt into other builder patterns by preceding your struct (or field) with `#[builder(pattern = "owned")]` or `#[builder(pattern = "immutable")]`. - **Extensible**: You can still define your own implementations for the builder struct and define additional methods. Just make sure to name them differently than the setter and build methods. - **Documentation and attributes**: Setter methods can be documented by simply documenting the corresponding field. Similarly `#[cfg(...)]` and `#[allow(...)]` attributes are also applied to the setter methods. - **Hidden fields**: You can skip setters via `#[builder(setter(skip))]` on each field individually. - **Setter visibility**: You can opt into private setter by preceding your struct with `#[builder(private)]`. - **Setter type conversions**: With `#[builder(setter(into))]`, setter methods will be generic over the input types – you can then supply every argument that implements the [`Into`][into] trait for the field type. - **Setter strip option**: With `#[builder(setter(strip_option))]`, setter methods will take `T` as parameter'type for field of type `Option`. - **Collection setters**: Adding `#[builder(setter(each(name = "method_name")))]` to fields whose types implement `Default` and `Extend` will generate a setter which adds items to the builder collection for that field. It's possible for these setters to be generic over the `Into` trait too, like so: `#[builder(setter(each(name = "foo", into)))]`. - **Builder field visibility**: You can use `#[builder(field(private))]` or `..(public)`, to set field visibility of your builder. - **Generic structs**: Are also supported, but you **must not** use a type parameter named `VALUE`, if you also activate setter type conversions. - **Default values**: You can use `#[builder(default)]` to delegate to the `Default` implementation or any explicit value via ` = ".."`. This works both on the struct and field level. - **Pre-build validation**: You can use `#[builder(build_fn(validate = "path::to::fn"))]` to add your own validation before the target struct is generated. - **Build method suppression**: You can use `#[builder(build_fn(skip))]` to disable auto-implementation of the build method and provide your own. - **Custom build method error types**: You can use `#[builder(build_fn(error = "path::to::Error"))]` to have your builder return an error type of your choosing. By default, the macro will emit an error type alongside the builder. - **Builder derivations**: You can use `#[builder(derive(Trait1, Trait2, ...))]` to have the builder derive additonal traits. All builders derive `Default` and `Clone`, so you should not declare those in this attribute. - **Pass-through attributes**: Use `#[builder_struct_attr(...)]`, `#[builder_impl_attr(...)]`, `#[builder_field_attr(...)]`, and `#[builder_setter_attr(...)]` to declare attributes that will be added to the relevant part of the generated builder. - **no_std support**: Just add `#[builder(no_std)]` to your struct and add `extern crate alloc` to your crate. - **Re-export support**: Use `#[builder(crate = "...")]` to set the root for `derive_builder`. This is useful if your crate is re-exporting `derive_builder::Builder` and needs the generated code to not directly reference the `derive_builder` crate. For more information and examples please take a look at our [documentation][doc]. ## Gotchas - Renaming `derive_builder` in `Cargo.toml` is not supported. - Tuple structs and unit structs are not supported as they have no field names. We do not intend to support them. - When defining a generic struct, you cannot use `VALUE` as a generic parameter as this is what all setters are using. ## [Documentation][doc] Detailed explaination of all features and tips for troubleshooting. You'll also find a discussion of different builder patterns. [doc]: https://colin-kiegel.github.io/rust-derive-builder [rust]: https://www.rust-lang.org/ [builder-pattern]: https://aturon.github.io/ownership/builders.html [into]: https://doc.rust-lang.org/nightly/std/convert/trait.Into.html ## [Changelog](CHANGELOG.md) Yes, we keep a changelog. ## License Licensed under either of - Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or ) - MIT license ([LICENSE-MIT](LICENSE-MIT) or ) at your option. ### Contribution 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. derive_builder-0.12.0/examples/channel.rs000064400000000000000000000013471046102023000164710ustar 00000000000000#![allow(dead_code)] #[macro_use] extern crate derive_builder; use std::convert::From; #[derive(PartialEq, Default, Debug, Clone)] struct Uuid(i32); #[derive(PartialEq, Default, Debug, Clone)] struct Authentication(i32); impl From for Uuid { fn from(x: i32) -> Uuid { Uuid(x) } } impl From for Authentication { fn from(x: i32) -> Authentication { Authentication(x) } } #[derive(Debug, Default, Builder)] #[builder(setter(into))] struct Channel { id: Uuid, token: Authentication, special_info: i32, } fn main() { let ch = ChannelBuilder::default() .special_info(42) .id(0) .token(5_494_192) .build() .unwrap(); println!("{:?}", ch); } derive_builder-0.12.0/examples/custom_constructor.rs000064400000000000000000000037371046102023000210450ustar 00000000000000#![allow(dead_code)] #[macro_use] extern crate derive_builder; #[derive(Debug, Clone)] pub enum ContentType { Json, Xml, } impl Default for ContentType { fn default() -> Self { Self::Json } } #[derive(Debug, Builder)] #[builder( custom_constructor, create_empty = "empty", build_fn(private, name = "fallible_build") )] pub struct ApiClient { // To make sure `host` and `key` are not changed after creation, tell derive_builder // to create the fields but not to generate setters. #[builder(setter(custom))] host: String, #[builder(setter(custom))] key: String, // uncommenting this field will cause the unit-test below to fail // baz: String, #[builder(default)] content_type: ContentType, } impl ApiClient { pub fn new(host: impl Into, key: impl Into) -> ApiClientBuilder { ApiClientBuilder { host: Some(host.into()), key: Some(key.into()), ..ApiClientBuilder::empty() } } } impl ApiClientBuilder { pub fn build(&self) -> ApiClient { self.fallible_build() .expect("All required fields were initialized") } } fn main() { dbg!(ApiClient::new("hello", "world") .content_type(ContentType::Xml) .build()); } #[cfg(test)] mod tests { use super::ApiClient; /// If any required fields are added to ApiClient and ApiClient::new was not updated, /// the field will be `None` when this "infallible" build method is called, resulting /// in a panic. Panicking is appropriate here, since the author of the builder promised /// the caller that it was safe to call new(...) followed immediately by build(), and /// the builder author is also the person who can correct the coding error by setting /// a default for the new property or changing the signature of `new` #[test] fn api_client_new_collects_all_required_fields() { ApiClient::new("hello", "world").build(); } } derive_builder-0.12.0/examples/custom_defaults.rs000064400000000000000000000024651046102023000202640ustar 00000000000000#[macro_use] extern crate derive_builder; #[derive(Builder, PartialEq, Debug)] struct Lorem { ipsum: String, #[builder(default = "self.default_dolor()?")] dolor: String, #[builder(default = "self.default_sit()?")] sit: String, #[builder(setter(skip), default = "self.default_amet()")] amet: String, } impl LoremBuilder { fn default_dolor(&self) -> Result { self.ipsum .clone() .ok_or_else(|| "ipsum must be initialized to build dolor".to_string()) } fn default_sit(&self) -> Result { match self.ipsum { Some(ref x) if x.chars().count() > 3 => Ok(format!("sit {}", x)), _ => Err("ipsum must at least 3 chars to build sit".to_string()), } } fn default_amet(&self) -> String { if let Some(ref x) = self.ipsum { format!("amet {}", x) } else { "..nothing there".to_string() } } } fn main() { let x = LoremBuilder::default() .ipsum("ipsum".to_string()) .build() .unwrap(); assert_eq!( x, Lorem { ipsum: "ipsum".to_string(), dolor: "ipsum".to_string(), sit: "sit ipsum".to_string(), amet: "amet ipsum".to_string(), } ); } derive_builder-0.12.0/examples/custom_error.rs000064400000000000000000000027241046102023000176040ustar 00000000000000//! This example shows using custom validation with a non-string error type. //! //! This relies on how the generated build function is constructed; the validator //! is invoked in conjunction with the `?` operator, so anything that converts to //! the generated `FooBuilderError` type is valid. #![allow(dead_code)] #[macro_use] extern crate derive_builder; use derive_builder::UninitializedFieldError; use std::fmt; fn validate_age(builder: &ExampleBuilder) -> Result<(), Error> { match builder.age { Some(age) if age > 150 => Err(Error::UnrealisticAge(age)), _ => Ok(()), } } #[derive(Debug, Builder)] #[builder(setter(into), build_fn(validate = "validate_age", error = "Error"))] struct Example { name: String, age: usize, } enum Error { UninitializedField(&'static str), UnrealisticAge(usize), } impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { Self::UnrealisticAge(age) => write!(f, "Nobody is {} years old", age), Self::UninitializedField(field) => write!(f, "Required field '{}' not set", field), } } } impl From for Error { fn from(e: UninitializedFieldError) -> Self { Self::UninitializedField(e.field_name()) } } fn main() { let person_err = ExampleBuilder::default() .name("Jane Doe") .age(200usize) .build() .unwrap_err(); println!("{}", person_err); } derive_builder-0.12.0/examples/custom_error_generic.rs000064400000000000000000000023201046102023000212700ustar 00000000000000//! This example shows combining generics with custom errors and validation. //! //! Note the use of the type parameter in the `#[builder(...)]` attribute. #![allow(dead_code)] #[macro_use] extern crate derive_builder; use derive_builder::UninitializedFieldError; trait Popular { fn is_popular(&self) -> bool; } impl<'a> Popular for &'a str { fn is_popular(&self) -> bool { !self.starts_with('b') } } #[derive(Debug, Builder)] #[builder(build_fn(validate = "check_person", error = "Error"))] struct Person { name: N, age: u16, } #[derive(Debug)] enum Error { UninitializedField(&'static str), UnpopularName(N), } impl From for Error { fn from(error: UninitializedFieldError) -> Self { Self::UninitializedField(error.field_name()) } } fn check_person(builder: &PersonBuilder) -> Result<(), Error> { if let Some(name) = &builder.name { if !name.is_popular() { return Err(Error::UnpopularName(name.clone())); } } Ok(()) } fn main() { dbg!(PersonBuilder::default() .name("bill") .age(71) .build() .unwrap_err()); } derive_builder-0.12.0/examples/deny_missing_docs.rs000064400000000000000000000010111046102023000205450ustar 00000000000000//! Some people may have `#![deny(missing_docs)]` in their crate. //! //! NOTE: This can only be tested in examples, but not integration tests. #![deny(missing_docs)] #[macro_use] extern crate derive_builder; /// Traditional form of communication. #[derive(Debug, Builder)] #[builder(setter(into))] pub struct Letter { /// Be creative. pub message: String, } fn main() { let x = LetterBuilder::default() .message("Hello World!") .build() .unwrap(); println!("{}", x.message); } derive_builder-0.12.0/examples/doc_example.rs000064400000000000000000000003571046102023000173410ustar 00000000000000// NOTE: generate fully expanded version with `cargo expand`. // // cargo expand --example doc_example #[macro_use] extern crate derive_builder; #[allow(dead_code)] #[derive(Builder)] struct Lorem { ipsum: u32, } fn main() {} derive_builder-0.12.0/examples/readme_example.rs000064400000000000000000000007651046102023000200340ustar 00000000000000// NOTE: generate fully expanded version with `cargo expand`. // // cargo expand --example readme_example #![allow(dead_code)] #[macro_use] extern crate derive_builder; #[derive(Default, Builder, Debug)] #[builder(setter(into))] struct Channel { token: i32, special_info: i32, } fn main() { // builder pattern, go, go, go!... let ch = ChannelBuilder::default() .special_info(42u8) .token(19_124) .build() .unwrap(); println!("{:?}", ch); } derive_builder-0.12.0/examples/validation.rs000064400000000000000000000016231046102023000172100ustar 00000000000000//! This example illustrates the use of `validate` to add a pre-build validation //! step. #[macro_use] extern crate derive_builder; #[derive(Builder, Debug, PartialEq)] #[builder(build_fn(validate = "Self::validate"))] struct Lorem { pub ipsum: u8, } impl LoremBuilder { /// Check that `Lorem` is putting in the right amount of effort. fn validate(&self) -> Result<(), String> { if let Some(ref ipsum) = self.ipsum { match *ipsum { i if i < 20 => Err("Try harder".to_string()), i if i > 100 => Err("You'll tire yourself out".to_string()), _ => Ok(()), } } else { Ok(()) } } } fn main() { // If we're trying too hard... let x = LoremBuilder::default().ipsum(120).build().unwrap_err(); // .. the build will fail: assert_eq!(&x.to_string(), "You'll tire yourself out"); } derive_builder-0.12.0/src/error.rs000064400000000000000000000017661046102023000151700ustar 00000000000000#[cfg(feature = "std")] use std::{error::Error, fmt}; #[cfg(not(feature = "std"))] use core::fmt; /// Runtime error when a `build()` method is called and one or more required fields /// do not have a value. #[derive(Debug, Clone)] pub struct UninitializedFieldError(&'static str); impl UninitializedFieldError { /// Create a new `UnitializedFieldError` for the specified field name. pub fn new(field_name: &'static str) -> Self { UninitializedFieldError(field_name) } /// Get the name of the first-declared field that wasn't initialized pub fn field_name(&self) -> &'static str { self.0 } } impl fmt::Display for UninitializedFieldError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "Field not initialized: {}", self.0) } } #[cfg(feature = "std")] impl Error for UninitializedFieldError {} impl From<&'static str> for UninitializedFieldError { fn from(field_name: &'static str) -> Self { Self::new(field_name) } } derive_builder-0.12.0/src/lib.rs000064400000000000000000000567371046102023000146150ustar 00000000000000//! Derive a builder for a struct //! //! This crate implements the [builder pattern] for you. //! Just apply `#[derive(Builder)]` to a struct `Foo`, and it will derive an additional //! struct `FooBuilder` with **setter**-methods for all fields and a **build**-method //! — the way you want it. //! //! # Quick Start //! //! Add `derive_builder` as a dependency to you `Cargo.toml`. //! //! ## What you write //! //! ```rust //! #[macro_use] //! extern crate derive_builder; //! //! #[derive(Builder)] //! struct Lorem { //! ipsum: u32, //! // .. //! } //! # fn main() {} //! ``` //! //! ## What you get //! //! ```rust //! # #[macro_use] //! # extern crate derive_builder; //! # use derive_builder::UninitializedFieldError; //! # //! # struct Lorem { //! # ipsum: u32, //! # } //! # fn main() {} //! # //! #[derive(Clone, Default)] //! struct LoremBuilder { //! ipsum: Option, //! } //! # // bodge for testing: //! # type LoremBuilderError = UninitializedFieldError; //! //! #[allow(dead_code)] //! impl LoremBuilder { //! pub fn ipsum(&mut self, value: u32) -> &mut Self { //! let mut new = self; //! new.ipsum = Some(value); //! new //! } //! //! fn build(&self) -> Result { //! Ok(Lorem { //! ipsum: Clone::clone(self.ipsum //! .as_ref() //! .ok_or(LoremBuilderError::from(UninitializedFieldError::new("ipsum")))?), //! }) //! } //! } //! ``` //! //! By default all generated setter-methods take and return `&mut self` //! (aka _non-consuming_ builder pattern). Accordingly, the build method also takes a //! reference by default. //! //! You can easily opt into different patterns and control many other aspects. //! //! The build method returns `Result`, where `T` is the struct you started with //! and E is a generated builder error type. //! It returns `Err` if you didn't initialize all fields and no default values were //! provided. //! //! # Builder Patterns //! //! Let's look again at the example above. You can now build structs like this: //! //! ```rust //! # #[macro_use] extern crate derive_builder; //! # #[derive(Builder)] struct Lorem { ipsum: u32 } //! # fn try_main() -> Result<(), Box> { //! let x: Lorem = LoremBuilder::default().ipsum(42).build()?; //! # Ok(()) //! # } fn main() { try_main().unwrap(); } //! ``` //! //! Ok, _chaining_ method calls is nice, but what if `ipsum(42)` should only happen if `geek = true`? //! //! So let's make this call conditional //! //! ```rust //! # #[macro_use] extern crate derive_builder; //! # #[derive(Builder)] struct Lorem { ipsum: u32 } //! # fn try_main() -> Result<(), Box> { //! # let geek = true; //! let mut builder = LoremBuilder::default(); //! if geek { //! builder.ipsum(42); //! } //! let x: Lorem = builder.build()?; //! # Ok(()) //! # } fn main() { try_main().unwrap(); } //! ``` //! //! Now it comes in handy that our setter methods take and return mutable references. Otherwise //! we would need to write something more clumsy like `builder = builder.ipsum(42)` to reassign //! the return value each time we have to call a setter conditionally. //! //! Setters with mutable references are therefore a convenient default for the builder //! pattern in Rust. //! //! But this is a free world and the choice is still yours! //! //! ## Owned, aka Consuming //! //! Precede your struct (or field) with `#[builder(pattern = "owned")]` to opt into this pattern. //! Builders generated with this pattern do not automatically derive `Clone`, which allows builders //! to be generated for structs with fields that do not derive `Clone`. //! //! * Setters take and return `self`. //! * PRO: Setter calls and final build method can be chained. //! * CON: If you don't chain your calls, you have to create a reference to each return value, //! e.g. `builder = builder.ipsum(42)`. //! //! ## Mutable, aka Non-Consuming (recommended) //! //! This pattern is recommended and active by default if you don't specify anything else. //! You can precede your struct (or field) with `#[builder(pattern = "mutable")]` //! to make this choice explicit. //! //! * Setters take and return `&mut self`. //! * PRO: Setter calls and final build method can be chained. //! * CON: The build method must clone or copy data to create something owned out of a //! mutable reference. Otherwise it could not be used in a chain. **(*)** //! //! ## Immutable //! //! Precede your struct (or field) with `#[builder(pattern = "immutable")]` to opt into this pattern. //! //! * Setters take and return `&self`. //! * PRO: Setter calls and final build method can be chained. //! * CON: If you don't chain your calls, you have to create a reference to each return value, //! e.g. `builder = builder.ipsum(42)`. //! * CON: The build method _and each setter_ must clone or copy data to create something owned //! out of a reference. **(*)** //! //! ## (*) Performance Considerations //! //! Luckily Rust is clever enough to optimize these clone-calls away in release builds //! for your every-day use cases. Thats quite a safe bet - we checked this for you. ;-) //! Switching to consuming signatures (=`self`) is unlikely to give you any performance //! gain, but very likely to restrict your API for non-chained use cases. //! //! # More Features //! //! ## Hidden Fields //! //! You can hide fields by skipping their setters on (and presence in) the builder struct. //! //! - Opt-out — skip setters via `#[builder(setter(skip))]` on individual fields. //! - Opt-in — set `#[builder(setter(skip))]` on the whole struct //! and enable individual setters via `#[builder(setter)]`. //! //! The types of skipped fields must implement `Default`. //! //! ```rust //! # #[macro_use] //! # extern crate derive_builder; //! # //! #[derive(Builder)] //! struct HiddenField { //! setter_present: u32, //! #[builder(setter(skip))] //! setter_skipped: u32, //! } //! # fn main() {} //! ``` //! //! Alternatively, you can use the more verbose form: //! //! - `#[builder(setter(skip = true))]` //! - `#[builder(setter(skip = false))]` //! //! ## Custom setters (skip autogenerated setters) //! //! Similarly to `setter(skip)`, you can say that you will provide your own setter methods. //! This simply suppresses the generation of the setter, leaving the field in the builder, //! as `Option`. //! //! ```rust //! # #[macro_use] //! # extern crate derive_builder; //! # //! #[derive(Builder)] //! struct SetterOptOut { //! #[builder(setter(custom))] //! custom_setter: u32, //! } //! impl SetterOptOutBuilder { //! fn custom_setter(&mut self, value: u32) { //! self.custom_setter = Some(value); //! } //! } //! # fn main() {} //! ``` //! //! Again, the more verbose form is accepted: //! //! - `#[builder(setter(custom = true))]` //! - `#[builder(setter(custom = false))]` //! //! ## Setter Visibility //! //! Setters are public by default. You can precede your struct (or field) with `#[builder(public)]` //! to make this explicit. //! //! Otherwise precede your struct (or field) with `#[builder(private)]` to opt into private //! setters. //! //! ## Generated builder struct name //! //! By default, the builder struct for `struct Foo` is `FooBuilder`. //! You can override this: //! //! ```rust //! # #[macro_use] //! # extern crate derive_builder; //! # //! #[derive(Builder)] //! #[builder(name = "FooConstructor")] //! struct Foo { } //! //! # fn main() -> Result<(), FooConstructorError> { //! let foo: Foo = FooConstructor::default().build()?; //! # Ok(()) //! # } //! ``` //! //! ## Setter Name/Prefix //! //! Setter methods are named after their corresponding field by default. //! //! - You can customize the setter name via `#[builder(setter(name = "foo"))`. //! - Alternatively you can set a prefix via `#[builder(setter(prefix = "xyz"))`, which will change //! the method name to `xyz_foo` if the field is named `foo`. Note that an underscore is //! inserted, since Rust favors snake case here. //! //! Prefixes can also be defined on the struct level, but renames only work on fields. Renames //! take precedence over prefix definitions. //! //! ## Generic Setters //! //! You can make each setter generic over the `Into`-trait. It's as simple as adding //! `#[builder(setter(into))]` to either a field or the whole struct. //! //! ```rust //! # #[macro_use] //! # extern crate derive_builder; //! # //! #[derive(Builder, Debug, PartialEq)] //! struct Lorem { //! #[builder(setter(into))] //! pub ipsum: String, //! } //! //! fn main() { //! // `"foo"` will be converted into a `String` automatically. //! let x = LoremBuilder::default().ipsum("foo").build().unwrap(); //! //! assert_eq!(x, Lorem { //! ipsum: "foo".to_string(), //! }); //! } //! ``` //! //! ## Setters for Option //! //! You can avoid to user to wrap value into `Some(...)` for field of type `Option`. It's as simple as adding //! `#[builder(setter(strip_option))]` to either a field or the whole struct. //! //! ```rust //! # #[macro_use] //! # extern crate derive_builder; //! # //! #[derive(Builder, Debug, PartialEq)] //! struct Lorem { //! #[builder(setter(into, strip_option))] //! pub ipsum: Option, //! #[builder(setter(into, strip_option), default)] //! pub foo: Option, //! } //! //! fn main() { //! // `"foo"` will be converted into a `String` automatically. //! let x = LoremBuilder::default().ipsum("foo").build().unwrap(); //! //! assert_eq!(x, Lorem { //! ipsum: Some("foo".to_string()), //! foo: None //! }); //! } //! ``` //! If you want to set the value to None when unset, then enable `default` on this field (or do not use `strip_option`). //! //! Limitation: only the `Option` type name is supported, not type alias nor `std::option::Option`. //! //! ## Fallible Setters //! //! Alongside the normal setter methods, you can expose fallible setters which are generic over //! the `TryInto` trait. TryInto is a not-yet-stable trait //! (see rust-lang issue [#33417](https://github.com/rust-lang/rust/issues/33417)) similar to //! `Into` with the key distinction that the conversion can fail, and therefore produces a //! `Result`. //! //! You can only declare the `try_setter` attribute today if you're targeting nightly, and you have //! to add `#![feature(try_from)]` to your crate to use it. //! //! ```rust //! # #[macro_use] //! # extern crate derive_builder; //! #[derive(Builder, Debug, PartialEq)] //! #[builder(try_setter, setter(into))] //! struct Lorem { //! pub name: String, //! pub ipsum: u8, //! } //! //! #[derive(Builder, Debug, PartialEq)] //! struct Ipsum { //! #[builder(try_setter, setter(into, name = "foo"))] //! pub dolor: u8, //! } //! //! fn main() { //! LoremBuilder::default() //! .try_ipsum(1u16).unwrap() //! .name("hello") //! .build() //! .expect("1 fits into a u8"); //! //! IpsumBuilder::default() //! .try_foo(1u16).unwrap() //! .build() //! .expect("1 fits into a u8"); //! } //! ``` //! //! ## Default Values //! //! You can define default values for each field via annotation by `#[builder(default = "...")]`, //! where `...` stands for any Rust expression and must be string-escaped, e.g. //! //! * `#[builder(default = "42")]` //! * `#[builder(default)]` delegates to the [`Default`] trait of the base type. //! //! The expression will be evaluated with each call to `build`. //! //! ```rust //! # #[macro_use] //! # extern crate derive_builder; //! # //! #[derive(Builder, Debug, PartialEq)] //! struct Lorem { //! #[builder(default = "42")] //! pub ipsum: u32, //! } //! //! fn main() { //! // If we don't set the field `ipsum`, //! let x = LoremBuilder::default().build().unwrap(); //! //! // .. the custom default will be used for `ipsum`: //! assert_eq!(x, Lorem { //! ipsum: 42, //! }); //! } //! ``` //! //! ### Tips on Defaults //! //! * The `#[builder(default)]` annotation can be used on the struct level, too. Overrides are //! still possible. //! * Delegate to a private helper method on `FooBuilder` for anything fancy. This way //! you will get _much better error diagnostics_ from the rust compiler and it will be _much //! more readable_ for other human beings. :-) //! * Defaults will not work while using `#[builder(build_fn(skip))]`. In this case, you'll //! need to handle default values yourself when converting from the builder, such as by //! using `.unwrap_or()` and `.unwrap_or_else()`. //! //! [`Default`]: https://doc.rust-lang.org/std/default/trait.Default.html //! //! ```rust //! # #[macro_use] //! # extern crate derive_builder; //! # //! # #[derive(Builder, PartialEq, Debug)] //! struct Lorem { //! ipsum: String, //! // Custom defaults can delegate to helper methods //! // and pass errors to the enclosing `build()` method via `?`. //! #[builder(default = "self.default_dolor()?")] //! dolor: String, //! } //! //! impl LoremBuilder { //! // Private helper method with access to the builder struct. //! fn default_dolor(&self) -> Result { //! match self.ipsum { //! Some(ref x) if x.chars().count() > 3 => Ok(format!("dolor {}", x)), //! _ => Err("ipsum must at least 3 chars to build dolor".to_string()), //! } //! } //! } //! //! # fn main() { //! # let x = LoremBuilder::default() //! # .ipsum("ipsum".to_string()) //! # .build() //! # .unwrap(); //! # //! # assert_eq!(x, Lorem { //! # ipsum: "ipsum".to_string(), //! # dolor: "dolor ipsum".to_string(), //! # }); //! # } //! ``` //! //! You can even reference other fields, but you have to remember that the builder struct //! will wrap every type in an Option ([as illustrated earlier](#what-you-get)). //! //! ## Generic Structs //! //! ```rust //! # #[macro_use] //! # extern crate derive_builder; //! # //! #[derive(Builder, Debug, PartialEq, Default, Clone)] //! struct GenLorem { //! ipsum: &'static str, //! dolor: T, //! } //! //! fn main() { //! let x = GenLoremBuilder::default().ipsum("sit").dolor(42).build().unwrap(); //! assert_eq!(x, GenLorem { ipsum: "sit".into(), dolor: 42 }); //! } //! ``` //! //! ## Build Method Customization //! //! You can rename or suppress the auto-generated build method, leaving you free to implement //! your own version. Suppression is done using `#[builder(build_fn(skip))]` at the struct level, //! and renaming is done with `#[builder(build_fn(name = "YOUR_NAME"))]`. //! //! ## Pre-Build Validation //! //! If you're using the provided `build` method, you can declare //! `#[builder(build_fn(validate = "path::to::fn"))]` to specify a validator function which gets //! access to the builder before construction. The path does not need to be fully-qualified, and //! will consider `use` statements made at module level. It must be accessible from the scope //! where the target struct is declared. //! //! The provided function must have the signature `(&FooBuilder) -> Result<_, String>`; //! the `Ok` variant is not used by the `build` method. //! //! ```rust //! # #[macro_use] //! # extern crate derive_builder; //! # //! #[derive(Builder, Debug, PartialEq)] //! #[builder(build_fn(validate = "Self::validate"))] //! struct Lorem { //! pub ipsum: u8, //! } //! //! impl LoremBuilder { //! /// Check that `Lorem` is putting in the right amount of effort. //! fn validate(&self) -> Result<(), String> { //! if let Some(ref ipsum) = self.ipsum { //! match *ipsum { //! i if i < 20 => Err("Try harder".to_string()), //! i if i > 100 => Err("You'll tire yourself out".to_string()), //! _ => Ok(()) //! } //! } else { //! Ok(()) //! } //! } //! } //! //! fn main() { //! // If we're trying too hard... //! let x = LoremBuilder::default().ipsum(120).build().unwrap_err(); //! //! // .. the build will fail: //! assert_eq!(&x.to_string(), "You'll tire yourself out"); //! } //! ``` //! //! Note: //! * Default values are applied _after_ validation, and will therefore not be validated! //! //! ## Additional Trait Derivations //! //! You can derive additional traits on the builder, including traits defined by other crates: //! //! ```rust //! # #[macro_use] //! # extern crate derive_builder; //! # //! #[derive(Builder, Clone)] //! #[builder(derive(Debug, PartialEq, Eq))] //! pub struct Lorem { //! foo: u8, //! bar: String, //! } //! //! fn main() { //! assert_eq!(LoremBuilder::default(), LoremBuilder::default()); //! } //! ``` //! //! Attributes declared for those traits are _not_ forwarded to the fields on the builder. //! //! ## Documentation Comments and Attributes //! //! `#[derive(Builder)]` copies doc comments and attributes (`#[...]`) from your fields //! to the according builder fields and setter-methods, if it is one of the following: //! //! * `/// ...` //! * `#[doc = ...]` //! * `#[cfg(...)]` //! * `#[allow(...)]` //! //! The whitelisting minimizes interference with other custom attributes like //! those used by Serde, Diesel, or others. //! //! ```rust //! # #[macro_use] //! # extern crate derive_builder; //! # //! #[derive(Builder)] //! struct Lorem { //! /// `ipsum` may be any `String` (be creative). //! ipsum: String, //! #[doc = r"`dolor` is the estimated amount of work."] //! dolor: i32, //! // `#[derive(Builder)]` understands conditional compilation via cfg-attributes, //! // i.e. => "no field = no setter". //! #[cfg(target_os = "macos")] //! #[allow(non_snake_case)] //! Im_a_Mac: bool, //! } //! # fn main() {} //! ``` //! //! ### Pass-through Attributes //! //! You can set attributes on elements of the builder using the `builder_*_attr` attributes: //! //! - `builder_struct_attr` adds attributes after `#[derive(...)]` on the builder struct. //! - `builder_impl_attr` adds attributes on the `impl` block //! - `builder_field_attr` adds attributes to field declarations in the builder struct. //! - `builder_setter_attr` adds attributes to the setter in the `impl` block. //! //! ```rust //! # #[macro_use] //! # extern crate derive_builder; //! # //! #[derive(Builder)] //! #[builder(derive(serde::Serialize))] //! #[builder_struct_attr(serde(rename_all = "camelCase"))] //! struct Lorem { //! #[builder_field_attr(serde(rename="dolor"))] //! ipsum: String, //! } //! //! # fn main() { //! let mut show = LoremBuilder::default(); //! show.ipsum("sit".into()); //! assert_eq!(serde_json::to_string(&show).unwrap(), r#"{"dolor":"sit"}"#); //! # } //! ``` //! //! # Error return type from autogenerated `build` function //! //! By default, `build` returns an autogenerated error type: //! //! ```rust //! # extern crate derive_builder; //! # use derive_builder::UninitializedFieldError; //! # use std::fmt::{self, Display}; //! # //! #[doc="Error type for LoremBuilder"] //! #[derive(Debug)] //! #[non_exhaustive] //! pub enum LoremBuilderError { // where `LoremBuilder` is the name of the builder struct //! /// Uninitialized field //! UninitializedField(&'static str), //! /// Custom validation error //! ValidationError(String), //! } //! //! impl From for LoremBuilderError { //! fn from(s: String) -> Self { Self::ValidationError(s) } //! } //! impl From for LoremBuilderError { // ... //! # fn from(s: UninitializedFieldError) -> Self { todo!() } } //! impl Display for LoremBuilderError { // ... //! # fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result { todo!() } } //! impl std::error::Error for LoremBuilderError {} //! ``` //! //! Alternatively, you can specify your own error type: //! ```rust //! # #[macro_use] //! # extern crate derive_builder; //! # use derive_builder::UninitializedFieldError; //! # //! #[derive(Builder, Debug, PartialEq)] //! #[builder(build_fn(error = "OurLoremError"))] //! struct Lorem { //! pub ipsum: u32, //! } //! //! struct OurLoremError(String); //! //! impl From for OurLoremError { //! fn from(ufe: UninitializedFieldError) -> OurLoremError { OurLoremError(ufe.to_string()) } //! } //! //! # fn main() { //! let err: OurLoremError = LoremBuilder::default().build().unwrap_err(); //! assert_eq!(&err.0, "Field not initialized: ipsum"); //! # } //! ``` //! //! # Completely custom fields in the builder //! //! Instead of having an `Option`, you can have whatever type you like: //! //! ```rust //! # #[macro_use] //! # extern crate derive_builder; //! #[derive(Debug, PartialEq, Default, Builder, Clone)] //! #[builder(derive(Debug, PartialEq))] //! struct Lorem { //! #[builder(setter(into), field(type = "u32"))] //! ipsum: u32, //! //! #[builder(field(type = "String", build = "()"))] //! dolor: (), //! //! #[builder(field(type = "&'static str", build = "self.amet.parse()?"))] //! amet: u32, //! } //! //! impl From for LoremBuilderError { // ... //! # fn from(e: std::num::ParseIntError) -> LoremBuilderError { //! # e.to_string().into() //! # } //! # } //! //! # fn main() { //! let mut builder = LoremBuilder::default(); //! builder.ipsum(42u16).dolor("sit".into()).amet("12"); //! assert_eq!(builder, LoremBuilder { ipsum: 42, dolor: "sit".into(), amet: "12" }); //! let lorem = builder.build().unwrap(); //! assert_eq!(lorem, Lorem { ipsum: 42, dolor: (), amet: 12 }); //! # } //! ``` //! //! The builder field type (`type =`) must implement `Default`. //! //! The argument to `build` must be a literal string containing Rust code for the contents of a block, which must evaluate to the type of the target field. //! It may refer to the builder struct as `self`, use `?`, etc. //! //! # **`#![no_std]`** Support (on Nightly) //! //! You can activate support for `#![no_std]` by adding `#[builder(no_std)]` to your struct //! and `#![feature(alloc)] extern crate alloc` to your crate. //! //! The latter requires the _nightly_ toolchain. //! //! # Troubleshooting //! //! ## Gotchas //! //! - Tuple structs and unit structs are not supported as they have no field //! names. //! - Generic setters introduce a type parameter `VALUE: Into<_>`. Therefore you can't use //! `VALUE` as a type parameter on a generic struct in combination with generic setters. //! - The `try_setter` attribute and `owned` builder pattern are not compatible in practice; //! an error during building will consume the builder, making it impossible to continue //! construction. //! - When re-exporting the underlying struct under a different name, the //! auto-generated documentation will not match. //! - If derive_builder depends on your crate, and vice versa, then a cyclic //! dependency would occur. To break it you could try to depend on the //! [`derive_builder_core`] crate instead. //! //! ## Report Issues and Ideas //! //! [Open an issue on GitHub](https://github.com/colin-kiegel/rust-derive-builder/issues) //! //! If possible please try to provide the debugging info if you experience unexpected //! compilation errors (see above). //! //! [builder pattern]: https://web.archive.org/web/20170701044756/https://aturon.github.io/ownership/builders.html //! [`derive_builder_core`]: https://crates.io/crates/derive_builder_core #![deny(warnings)] #![cfg_attr(not(feature = "std"), no_std)] #[cfg(not(feature = "std"))] extern crate alloc; extern crate derive_builder_macro; mod error; pub use derive_builder_macro::Builder; #[doc(inline)] pub use error::UninitializedFieldError; #[doc(hidden)] pub mod export { pub mod core { #[cfg(not(feature = "std"))] pub use alloc::string; #[cfg(not(feature = "std"))] pub use core::*; #[cfg(feature = "std")] pub use std::*; } } derive_builder-0.12.0/tests/bounds_generation.rs000064400000000000000000000036451046102023000201150ustar 00000000000000#[macro_use] extern crate derive_builder; /// A struct that deliberately doesn't implement `Clone`. #[derive(Debug, Default, PartialEq, Eq)] pub struct Dolor(String); /// Notice that this type derives Builder without disallowing /// `Lorem`. #[derive(Debug, Clone, Builder, PartialEq, Eq, Default)] #[builder(field(private), setter(into))] pub struct Lorem { ipsum: T, } #[derive(Debug, Clone, Builder, PartialEq, Eq, Default)] #[builder(field(private))] pub struct VecLorem { ipsum: Vec, } #[derive(Debug, Clone, Builder, PartialEq, Eq)] #[builder(pattern = "owned", field(private))] pub struct OwnedLorem { ipsum: T, } #[test] fn generic_field_with_clone_has_builder_impl() { assert_eq!( LoremBuilder::default().ipsum(10).build().unwrap(), Lorem { ipsum: 10 } ); } /// The `LoremBuilder` type does not require that `T: Clone`, so we should /// be able to name a `LoremBuilder`. But all the methods are on an impl /// bound with `T: Clone`, so we can't do anything with it. #[test] fn builder_with_non_clone_generic_compiles() { let _: LoremBuilder; } /// In this case, we're trying to emit something that converts into a thing that /// implements clone. #[test] fn builder_with_into_generic_compiles() { assert_eq!( LoremBuilder::::default().ipsum("").build().unwrap(), Lorem::default() ); } #[test] fn builder_with_vec_t_compiles() { assert_eq!( VecLoremBuilder::::default() .ipsum(vec!["Hello".to_string()]) .build() .unwrap(), VecLorem { ipsum: vec!["Hello".to_string()], } ); } #[test] fn generic_field_without_clone_has_owned_builder() { assert_eq!( OwnedLoremBuilder::default() .ipsum(Dolor::default()) .build() .unwrap(), OwnedLorem { ipsum: Dolor::default() } ); } derive_builder-0.12.0/tests/build_fn.rs000064400000000000000000000031021046102023000161560ustar 00000000000000#[macro_use] extern crate derive_builder; #[derive(Debug, Builder, PartialEq)] #[builder(build_fn(skip))] pub struct Lorem { percentile: u8, } #[derive(Debug, Builder, PartialEq)] #[builder(build_fn(name = "finish"))] pub struct Ipsum { percentile: u8, } impl Lorem { pub fn new(pct: u8) -> Result { if pct <= 100 { Ok(Lorem { percentile: pct }) } else { Err(format!("Percentile must be between 0 and 100; was {}", pct)) } } } impl LoremBuilder { pub fn build(&self) -> Result { if let Some(ref pct) = self.percentile { Lorem::new(*pct) } else { Err("Percentile was not initialized".to_string()) } } } impl IpsumBuilder { /// This should be fine, because we renamed the generated build_fn. #[allow(dead_code)] fn build(&self) -> Result { unimplemented!() } } #[test] fn happy_path() { let lorem = LoremBuilder::default().percentile(80).build().unwrap(); assert_eq!(lorem, Lorem { percentile: 80 }); } #[test] fn uninitialized() { let lorem_err = LoremBuilder::default().build().unwrap_err(); assert_eq!("Percentile was not initialized", &lorem_err); } #[test] fn out_of_range() { let lorem_err = LoremBuilder::default().percentile(120).build().unwrap_err(); assert_eq!("Percentile must be between 0 and 100; was 120", &lorem_err); } #[test] fn rename() { let ipsum = IpsumBuilder::default().percentile(110).finish().unwrap(); assert_eq!(Ipsum { percentile: 110 }, ipsum); } derive_builder-0.12.0/tests/builder_field_custom.rs000064400000000000000000000021471046102023000205670ustar 00000000000000#[macro_use] extern crate pretty_assertions; #[macro_use] extern crate derive_builder; use std::num::ParseIntError; #[derive(Debug, PartialEq, Default, Builder, Clone)] pub struct Lorem { #[builder(field(type = "Option", build = "self.ipsum.unwrap_or(42) + 1"))] ipsum: usize, #[builder(setter(into), field(type = "String", build = "self.dolor.parse()?"))] dolor: u32, } impl From for LoremBuilderError { fn from(e: ParseIntError) -> LoremBuilderError { LoremBuilderError::ValidationError(e.to_string()) } } #[test] fn custom_fields() { let x = LoremBuilder::default().dolor("7").build().unwrap(); assert_eq!( x, Lorem { ipsum: 43, dolor: 7, } ); let x = LoremBuilder::default() .ipsum(Some(12)) .dolor("66") .build() .unwrap(); assert_eq!( x, Lorem { ipsum: 13, dolor: 66, } ); let x = LoremBuilder::default().build().unwrap_err().to_string(); assert_eq!(x, "cannot parse integer from empty string"); } derive_builder-0.12.0/tests/builder_name.rs000064400000000000000000000014621046102023000170310ustar 00000000000000#[macro_use] extern crate pretty_assertions; #[macro_use] extern crate derive_builder; #[derive(Debug, PartialEq, Default, Builder, Clone)] #[builder(name = "MyBuilder")] struct Lorem { ipsum: &'static str, pub dolor: Option<&'static str>, pub sit: i32, amet: bool, } #[test] fn error_if_uninitialized() { let error = MyBuilder::default().build().unwrap_err(); assert_eq!(&error.to_string(), "`ipsum` must be initialized"); } #[test] fn builder_test() { let x: Lorem = MyBuilder::default() .ipsum("lorem") .dolor(Some("dolor")) .sit(42) .amet(true) .build() .unwrap(); assert_eq!( x, Lorem { ipsum: "lorem", dolor: Some("dolor"), sit: 42, amet: true, } ); } derive_builder-0.12.0/tests/compile-fail/builder_field_attr.rs000064400000000000000000000003251046102023000225640ustar 00000000000000#[macro_use] extern crate derive_builder; #[derive(Debug, PartialEq, Default, Builder, Clone)] pub struct Lorem { ok: String, #[builder_field_attr(no_such_attribute)] broken: String, } fn main() {} derive_builder-0.12.0/tests/compile-fail/builder_field_attr.stderr000064400000000000000000000003261046102023000234440ustar 00000000000000error: cannot find attribute `no_such_attribute` in this scope --> tests/compile-fail/builder_field_attr.rs:8:26 | 8 | #[builder_field_attr(no_such_attribute)] | ^^^^^^^^^^^^^^^^^ derive_builder-0.12.0/tests/compile-fail/builder_field_custom.rs000064400000000000000000000011371046102023000231260ustar 00000000000000#[macro_use] extern crate derive_builder; #[derive(Debug, PartialEq, Default, Builder, Clone)] pub struct Lorem { // `default` is incompatible with `field.build` #[builder( default = "1", field(build = "self.ipsum.map(|v| v + 42).unwrap_or(100)") )] ipsum: usize, // `default` is incompatible with `field.type`, even without `field.build` #[builder(default = "2", field(type = "usize"))] sit: usize, // Both errors can occur on the same field #[builder(default = "3", field(type = "usize", build = "self.ipsum + 42"))] amet: usize, } fn main() {} derive_builder-0.12.0/tests/compile-fail/builder_field_custom.stderr000064400000000000000000000017021046102023000240030ustar 00000000000000error: #[builder(default)] and #[builder(field(build="..."))] cannot be used together --> tests/compile-fail/builder_field_custom.rs:8:19 | 8 | default = "1", | ^^^ error: #[builder(default)] and #[builder(field(type="..."))] cannot be used together --> tests/compile-fail/builder_field_custom.rs:14:25 | 14 | #[builder(default = "2", field(type = "usize"))] | ^^^ error: #[builder(default)] and #[builder(field(build="..."))] cannot be used together --> tests/compile-fail/builder_field_custom.rs:18:25 | 18 | #[builder(default = "3", field(type = "usize", build = "self.ipsum + 42"))] | ^^^ error: #[builder(default)] and #[builder(field(type="..."))] cannot be used together --> tests/compile-fail/builder_field_custom.rs:18:25 | 18 | #[builder(default = "3", field(type = "usize", build = "self.ipsum + 42"))] | ^^^ derive_builder-0.12.0/tests/compile-fail/builder_setter_attr.rs000064400000000000000000000004201046102023000230030ustar 00000000000000#![deny(unused_must_use)] #[macro_use] extern crate derive_builder; #[derive(Debug, PartialEq, Default, Builder, Clone)] pub struct Lorem { ok: String, #[builder_setter_attr(must_use)] broken: usize, } fn main() { LoremBuilder::default().broken(42); } derive_builder-0.12.0/tests/compile-fail/builder_setter_attr.stderr000064400000000000000000000005721046102023000236720ustar 00000000000000error: unused return value of `LoremBuilder::broken` that must be used --> tests/compile-fail/builder_setter_attr.rs:15:5 | 15 | LoremBuilder::default().broken(42); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: the lint level is defined here --> tests/compile-fail/builder_setter_attr.rs:1:9 | 1 | #![deny(unused_must_use)] | ^^^^^^^^^^^^^^^ derive_builder-0.12.0/tests/compile-fail/crate_root.rs000064400000000000000000000007571046102023000211130ustar 00000000000000#[macro_use] extern crate derive_builder; // This is a stand-in for any bad crate directive mod empty {} #[derive(Builder)] // It would be nice if the "failed to resolve" errors would identify `"empty"` as the error span, // but doing so would require rewriting a lot of the code generation to use the crate_root span // for the full path of the thing being imported, and that doesn't seem worth the code churn. #[builder(crate = "empty")] struct BadCrate { lorem: String, } fn main() {} derive_builder-0.12.0/tests/compile-fail/crate_root.stderr000064400000000000000000000066271046102023000217740ustar 00000000000000error[E0433]: failed to resolve: could not find `export` in `empty` --> tests/compile-fail/crate_root.rs:7:10 | 7 | #[derive(Builder)] | ^^^^^^^ could not find `export` in `empty` | = note: this error originates in the derive macro `Builder` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0433]: failed to resolve: could not find `export` in `empty` --> tests/compile-fail/crate_root.rs:7:10 | 7 | #[derive(Builder)] | ^^^^^^^ not found in `empty::export::core::option` | = note: this error originates in the derive macro `Builder` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider importing this enum | 5 | use derive_builder::export::core::option::Option; | error[E0433]: failed to resolve: could not find `export` in `empty` --> tests/compile-fail/crate_root.rs:7:10 | 7 | #[derive(Builder)] | ^^^^^^^ not found in `empty::export::core::clone` | = note: this error originates in the derive macro `Builder` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider importing this trait | 5 | use derive_builder::export::core::clone::Clone; | error[E0433]: failed to resolve: could not find `export` in `empty` --> tests/compile-fail/crate_root.rs:7:10 | 7 | #[derive(Builder)] | ^^^^^^^ not found in `empty::export::core::result` | = note: this error originates in the derive macro `Builder` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider importing one of these items | 5 | use derive_builder::export::core::fmt::Result; | 5 | use derive_builder::export::core::io::Result; | 5 | use derive_builder::export::core::result::Result; | 5 | use derive_builder::export::core::thread::Result; | error[E0433]: failed to resolve: could not find `export` in `empty` --> tests/compile-fail/crate_root.rs:7:10 | 7 | #[derive(Builder)] | ^^^^^^^ not found in `empty::export::core::convert` | = note: this error originates in the derive macro `Builder` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider importing this trait | 5 | use derive_builder::export::core::convert::Into; | error[E0433]: failed to resolve: could not find `UninitializedFieldError` in `empty` --> tests/compile-fail/crate_root.rs:7:10 | 7 | #[derive(Builder)] | ^^^^^^^ not found in `empty` | = note: this error originates in the derive macro `Builder` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider importing this struct | 5 | use derive_builder::UninitializedFieldError; | error[E0433]: failed to resolve: could not find `export` in `empty` --> tests/compile-fail/crate_root.rs:7:10 | 7 | #[derive(Builder)] | ^^^^^^^ not found in `empty::export::core::default` | = note: this error originates in the derive macro `Builder` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider importing this trait | 5 | use derive_builder::export::core::default::Default; | error[E0412]: cannot find type `UninitializedFieldError` in module `empty` --> tests/compile-fail/crate_root.rs:7:10 | 7 | #[derive(Builder)] | ^^^^^^^ not found in `empty` | = note: this error originates in the derive macro `Builder` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider importing this struct | 5 | use derive_builder::UninitializedFieldError; | derive_builder-0.12.0/tests/compile-fail/custom_error_generic_missing_bound.rs000064400000000000000000000016111046102023000260770ustar 00000000000000#[macro_use] extern crate derive_builder; use derive_builder::UninitializedFieldError; trait Popular { fn is_popular(&self) -> bool; } impl<'a> Popular for &'a str { fn is_popular(&self) -> bool { !self.starts_with('b') } } #[derive(Debug, Builder)] #[builder(build_fn(validate = "check_person", error = "Error"))] struct Person { name: N, age: u16, } enum Error { UninitializedField(&'static str), UnpopularName(N), } impl From for Error { fn from(error: UninitializedFieldError) -> Self { Self::UninitializedField(error.field_name()) } } fn check_person(builder: &PersonBuilder) -> Result<(), Error> { if let Some(name) = &builder.name { if !name.is_popular() { return Err(Error::UnpopularName(name.clone())); } } Ok(()) } fn main() {} derive_builder-0.12.0/tests/compile-fail/custom_error_generic_missing_bound.stderr000064400000000000000000000013051046102023000267560ustar 00000000000000error[E0277]: the trait bound `N: Popular` is not satisfied --> tests/compile-fail/custom_error_generic_missing_bound.rs:17:31 | 17 | #[builder(build_fn(validate = "check_person", error = "Error"))] | ^^^^^^^^^^^^^^ the trait `Popular` is not implemented for `N` | note: required by a bound in `check_person` --> tests/compile-fail/custom_error_generic_missing_bound.rs:34:20 | 34 | fn check_person(builder: &PersonBuilder) -> Result<(), Error> { | ^^^^^^^ required by this bound in `check_person` help: consider restricting type parameter `N` | 18 | struct Person { | +++++++++ derive_builder-0.12.0/tests/compile-fail/custom_error_no_from.rs000064400000000000000000000015111046102023000232010ustar 00000000000000#[macro_use] extern crate derive_builder; fn validate_age(age: usize) -> Result<(), Error> { if age > 200 { Err(Error::UnrealisticAge(age)) } else { Ok(()) } } fn check_person(builder: &PersonBuilder) -> Result<(), Error> { if let Some(age) = builder.age { validate_age(age) } else { Ok(()) } } #[derive(Builder)] #[builder(build_fn(validate = "check_person", error = "Error"))] struct Person { name: String, age: usize, } // NOTE: This enum has a variant for the uninitialized field case (called MissingData) // but has forgotten `impl From`, which is a // compile-blocking mistake. #[derive(Debug)] enum Error { /// A required field is not filled out. MissingData(&'static str), UnrealisticAge(usize), } fn main() {} derive_builder-0.12.0/tests/compile-fail/custom_error_no_from.stderr000064400000000000000000000007241046102023000240650ustar 00000000000000error[E0277]: the trait bound `Error: From` is not satisfied --> tests/compile-fail/custom_error_no_from.rs:21:55 | 21 | #[builder(build_fn(validate = "check_person", error = "Error"))] | ^^^^^^^ the trait `From` is not implemented for `Error` | = note: required because of the requirements on the impl of `Into` for `UninitializedFieldError` derive_builder-0.12.0/tests/compile-fail/deny_empty_default.rs000064400000000000000000000003721046102023000226240ustar 00000000000000#[macro_use] extern crate derive_builder; // deny `#[builder(default = "")]`, because we don't want to define a meaning (yet)! :-) #[allow(dead_code)] #[derive(Builder)] struct Lorem { #[builder(default = "")] ipsum: String, } fn main() {} derive_builder-0.12.0/tests/compile-fail/deny_empty_default.stderr000064400000000000000000000002111046102023000234730ustar 00000000000000error: Unknown literal value `` --> $DIR/deny_empty_default.rs:8:25 | 8 | #[builder(default = "")] | ^^ derive_builder-0.12.0/tests/compile-fail/private_build_fn.rs000064400000000000000000000012771046102023000222640ustar 00000000000000#[macro_use] extern crate derive_builder; mod container { /// `LoremBuilder` should be accessible outside the module, but its /// build method should not be. #[derive(Debug, Default, Builder)] #[builder(default, public, build_fn(private))] pub struct Lorem { foo: usize, bar: String, } impl LoremBuilder { /// Create a `Lorem` pub fn my_build(&self) -> Lorem { self.build().expect("All good") } } } fn main() { use container::{Lorem, LoremBuilder}; let lorem1 = LoremBuilder::default().my_build(); let lorem2 = LoremBuilder::default().build().unwrap(); println!("{:?} vs {:?}", lorem1, lorem2); } derive_builder-0.12.0/tests/compile-fail/private_build_fn.stderr000064400000000000000000000011371046102023000231360ustar 00000000000000warning: unused import: `Lorem` --> tests/compile-fail/private_build_fn.rs:23:21 | 23 | use container::{Lorem, LoremBuilder}; | ^^^^^ | = note: `#[warn(unused_imports)]` on by default error[E0624]: associated function `build` is private --> tests/compile-fail/private_build_fn.rs:27:42 | 7 | #[derive(Debug, Default, Builder)] | ------- private associated function defined here ... 27 | let lorem2 = LoremBuilder::default().build().unwrap(); | ^^^^^ private associated function derive_builder-0.12.0/tests/compile-fail/private_builder.rs000064400000000000000000000010471046102023000221230ustar 00000000000000#[macro_use] extern crate derive_builder; pub mod foo { /// The builder struct's declaration of privacy should override the field's /// attempt to be public later on. #[derive(Debug, PartialEq, Default, Builder, Clone)] #[builder(private, setter(into))] pub struct Lorem { pub private: String, #[builder(public)] pub public: String, } } fn main() { let x = foo::LoremBuilder::default() .public("Hello") .build() .unwrap(); assert_eq!(x.public, "Hello".to_string()); } derive_builder-0.12.0/tests/compile-fail/private_builder.stderr000064400000000000000000000015651046102023000230070ustar 00000000000000error[E0603]: struct `LoremBuilder` is private --> tests/compile-fail/private_builder.rs:17:18 | 17 | let x = foo::LoremBuilder::default() | ^^^^^^^^^^^^ private struct | note: the struct `LoremBuilder` is defined here --> tests/compile-fail/private_builder.rs:7:41 | 7 | #[derive(Debug, PartialEq, Default, Builder, Clone)] | ^^^^^^^ = note: this error originates in the derive macro `Builder` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0624]: associated function `build` is private --> tests/compile-fail/private_builder.rs:19:10 | 7 | #[derive(Debug, PartialEq, Default, Builder, Clone)] | ------- private associated function defined here ... 19 | .build() | ^^^^^ private associated function derive_builder-0.12.0/tests/compile-fail/private_fields.rs000064400000000000000000000012641046102023000217440ustar 00000000000000#[macro_use] extern crate derive_builder; /// This builder is in an inner module to make sure private fields aren't accessible /// from the `main` function. mod inner { /// The `LoremBuilder` struct will have private fields for `ipsum` and `dolor`, and /// a public `sit` field. #[derive(Debug, Builder)] #[builder(field(private), setter(into))] pub struct Lorem { ipsum: String, dolor: u16, #[builder(field(public))] sit: bool, } } fn main() { use inner::LoremBuilder; let mut lorem = LoremBuilder::default(); lorem.dolor(15u16); lorem.sit = Some(true); // <-- public lorem.dolor = Some(0); // <-- private } derive_builder-0.12.0/tests/compile-fail/private_fields.stderr000064400000000000000000000003101046102023000226120ustar 00000000000000error[E0616]: field `dolor` of struct `LoremBuilder` is private --> tests/compile-fail/private_fields.rs:25:11 | 25 | lorem.dolor = Some(0); // <-- private | ^^^^^ private field derive_builder-0.12.0/tests/compile-fail/rename_setter_struct_level.rs000064400000000000000000000007751046102023000244020ustar 00000000000000#[macro_use] extern crate pretty_assertions; #[macro_use] extern crate derive_builder; #[derive(Debug, PartialEq, Default, Builder, Clone)] #[builder(setter(name = "foo"))] struct Lorem { ipsum: &'static str, pub dolor: &'static str, } fn main() { let x = LoremBuilder::default() .ipsum("ipsum") .foo("dolor") .build() .unwrap(); assert_eq!(x, Lorem { ipsum: "ipsum", dolor: "dolor", }); } derive_builder-0.12.0/tests/compile-fail/rename_setter_struct_level.stderr000064400000000000000000000006221046102023000252500ustar 00000000000000error: Unknown field: `name` --> tests/compile-fail/rename_setter_struct_level.rs:7:18 | 7 | #[builder(setter(name = "foo"))] | ^^^^ error[E0433]: failed to resolve: use of undeclared type `LoremBuilder` --> tests/compile-fail/rename_setter_struct_level.rs:14:13 | 14 | let x = LoremBuilder::default() | ^^^^^^^^^^^^ use of undeclared type `LoremBuilder` derive_builder-0.12.0/tests/compile-fail/vis_conflict.rs000064400000000000000000000006771046102023000214350ustar 00000000000000#[macro_use] extern crate derive_builder; #[derive(Builder)] #[builder(public, vis = "pub(crate)")] pub struct Example { #[builder(public, private)] field: String, } #[derive(Builder)] #[builder(public, vis = "pub(crate)", build_fn(private, public))] pub struct SecondExample { #[builder(private, vis = "pub")] a_field: String, } fn main() { ExampleBuilder::default().build(); SecondExampleBuilder::default().build(); } derive_builder-0.12.0/tests/compile-fail/vis_conflict.stderr000064400000000000000000000027561046102023000223140ustar 00000000000000error: `public` and `private` cannot be used together --> tests/compile-fail/vis_conflict.rs:7:15 | 7 | #[builder(public, private)] | ^^^^^^ error: `vis="..."` cannot be used with `public` or `private` --> tests/compile-fail/vis_conflict.rs:5:25 | 5 | #[builder(public, vis = "pub(crate)")] | ^^^^^^^^^^^^ error: `public` and `private` cannot be used together --> tests/compile-fail/vis_conflict.rs:12:57 | 12 | #[builder(public, vis = "pub(crate)", build_fn(private, public))] | ^^^^^^ error: `vis="..."` cannot be used with `public` or `private` --> tests/compile-fail/vis_conflict.rs:14:30 | 14 | #[builder(private, vis = "pub")] | ^^^^^ error: `vis="..."` cannot be used with `public` or `private` --> tests/compile-fail/vis_conflict.rs:12:25 | 12 | #[builder(public, vis = "pub(crate)", build_fn(private, public))] | ^^^^^^^^^^^^ error[E0433]: failed to resolve: use of undeclared type `ExampleBuilder` --> tests/compile-fail/vis_conflict.rs:19:5 | 19 | ExampleBuilder::default().build(); | ^^^^^^^^^^^^^^ use of undeclared type `ExampleBuilder` error[E0433]: failed to resolve: use of undeclared type `SecondExampleBuilder` --> tests/compile-fail/vis_conflict.rs:20:5 | 20 | SecondExampleBuilder::default().build(); | ^^^^^^^^^^^^^^^^^^^^ use of undeclared type `SecondExampleBuilder` derive_builder-0.12.0/tests/compiletests.rs000064400000000000000000000003761046102023000171210ustar 00000000000000#![cfg(compiletests)] extern crate rustversion; extern crate trybuild; #[rustversion::stable(1.59)] #[test] fn compile_test() { let t = trybuild::TestCases::new(); t.pass("tests/run-pass/*.rs"); t.compile_fail("tests/compile-fail/*.rs"); } derive_builder-0.12.0/tests/custom_constructor.rs000064400000000000000000000022251046102023000203600ustar 00000000000000#[macro_use] extern crate pretty_assertions; #[macro_use] extern crate derive_builder; #[derive(Debug, PartialEq, Eq, Builder)] #[builder(custom_constructor, build_fn(private, name = "fallible_build"))] struct Request { url: &'static str, username: &'static str, #[builder(default, setter(into))] password: Option<&'static str>, } impl RequestBuilder { pub fn new(url: &'static str, username: &'static str) -> Self { Self { url: Some(url), username: Some(username), ..Self::create_empty() } } pub fn build(&self) -> Request { self.fallible_build() .expect("All required fields set upfront") } } #[test] fn new_then_build_succeeds() { assert_eq!( RequestBuilder::new("...", "!!!").build(), Request { url: "...", username: "!!!", password: None } ); } #[test] fn new_then_set_succeeds() { assert_eq!( RequestBuilder::new("...", "!!!").password("test").build(), Request { url: "...", username: "!!!", password: Some("test") } ); } derive_builder-0.12.0/tests/custom_default.rs000064400000000000000000000077201046102023000174240ustar 00000000000000#[macro_use] extern crate pretty_assertions; #[macro_use] extern crate derive_builder; mod field_level { use derive_builder::UninitializedFieldError; #[derive(Debug, PartialEq, Default, Builder, Clone)] struct Lorem { required: String, #[builder(default)] explicit_default: String, #[builder(default = "\"foo\".to_string()")] escaped_default: String, #[builder(default = r#"format!("Hello {}!", "World")"#)] raw_default: String, #[builder(default = r#"format!("{}-{}-{}-{}", Clone::clone(self.required .as_ref() .ok_or_else(|| UninitializedFieldError::new("required"))?), match self.explicit_default { Some(ref x) => x, None => "EMPTY" }, self.escaped_default.as_ref().map(|x| x.as_ref()).unwrap_or("EMPTY"), if let Some(ref x) = self.raw_default { x } else { "EMPTY" })"#)] computed_default: String, } #[test] fn error_if_uninitialized() { let error = LoremBuilder::default().build().unwrap_err(); assert_eq!(&error.to_string(), "`required` must be initialized"); } #[test] fn custom_default() { let x = LoremBuilder::default() .required("ipsum".to_string()) .build() .unwrap(); assert_eq!( x, Lorem { required: "ipsum".to_string(), explicit_default: "".to_string(), escaped_default: "foo".to_string(), raw_default: "Hello World!".to_string(), computed_default: "ipsum-EMPTY-EMPTY-EMPTY".to_string(), } ); } #[test] fn builder_test() { let x = LoremBuilder::default() .required("ipsum".to_string()) .explicit_default("lorem".to_string()) .escaped_default("dolor".to_string()) .raw_default("sit".to_string()) .build() .unwrap(); assert_eq!( x, Lorem { required: "ipsum".to_string(), explicit_default: "lorem".to_string(), escaped_default: "dolor".to_string(), raw_default: "sit".to_string(), computed_default: "ipsum-lorem-dolor-sit".to_string(), } ); } } mod struct_level { #[derive(Debug, Clone, PartialEq, Eq, Builder)] #[builder(default = "explicit_default()")] struct Lorem { #[builder(default = "true")] overwritten: bool, not_type_default: Option<&'static str>, } fn explicit_default() -> Lorem { Lorem { overwritten: false, not_type_default: Some("defined on struct-level"), } } #[derive(Debug, Clone, PartialEq, Eq, Builder)] #[builder(default)] struct Ipsum { not_type_default: Option, also_custom: bool, is_type_default: String, } impl Default for Ipsum { fn default() -> Self { Ipsum { not_type_default: Some(20), also_custom: true, is_type_default: Default::default(), } } } #[test] fn explicit_defaults_are_equal() { let lorem = LoremBuilder::default().build().unwrap(); assert_eq!( lorem, Lorem { overwritten: true, ..explicit_default() } ); } #[test] fn implicit_defaults_are_equal() { let ipsum = IpsumBuilder::default().build().unwrap(); assert_eq!(ipsum, Ipsum::default()); } #[test] fn overrides_work() { let ipsum = IpsumBuilder::default() .not_type_default(None) .build() .expect("Struct-level default makes all fields optional"); assert_eq!(ipsum.not_type_default, None); } } derive_builder-0.12.0/tests/derive_trait.rs000064400000000000000000000012271046102023000170630ustar 00000000000000#![allow(dead_code)] #[macro_use] extern crate derive_builder; #[derive(Debug, Default, Clone)] struct NotPartialEq(String); #[derive(Debug, Clone, Builder)] #[builder(derive(Debug, PartialEq, Eq))] struct Lorem { foo: u8, /// This type doesn't have `PartialEq` support, but that's fine /// since we don't want it in the builder. #[builder(setter(skip))] excluded: NotPartialEq, } #[test] fn defaults() { // This macro requires that the two sides implement `PartialEq` AND `Debug`, // so this one line is testing that the requested traits were really generated. assert_eq!(LoremBuilder::default(), LoremBuilder::default()); } derive_builder-0.12.0/tests/forward_allow_attr.rs000064400000000000000000000011131046102023000202700ustar 00000000000000#![deny(non_snake_case)] #[macro_use] extern crate derive_builder; #[derive(Builder)] // If this attribute is not forwarded to both the struct and the impl block, there would // be a compile error on either the field or the setter method name. Therefore, forwarding // is working as-expected if this test compiles. #[allow(non_snake_case)] pub struct Example { aPascalName: &'static str, } fn main() { assert_eq!( ExampleBuilder::default() .aPascalName("hello") .build() .unwrap() .aPascalName, "hello" ); } derive_builder-0.12.0/tests/forward_serde_attrs.rs000064400000000000000000000013221046102023000204410ustar 00000000000000#[macro_use] extern crate derive_builder; extern crate serde; extern crate serde_json; #[derive(Builder)] #[builder(setter(into), derive(serde::Serialize))] #[builder_struct_attr(serde(rename_all = "camelCase"))] #[allow(dead_code)] struct Example { first_name: String, middle_name: String, #[builder_field_attr(serde(rename = "familyName"))] last_name: String, } #[test] fn serialize_builder() { assert_eq!( serde_json::to_string( &ExampleBuilder::default() .first_name("Jane") .middle_name("Alice") .last_name("Doe"), ) .unwrap(), r#"{"firstName":"Jane","middleName":"Alice","familyName":"Doe"}"# ); } derive_builder-0.12.0/tests/generic_structs.rs000064400000000000000000000022021046102023000175770ustar 00000000000000#[macro_use] extern crate pretty_assertions; #[macro_use] extern crate derive_builder; use std::clone::Clone; use std::fmt::Display; #[derive(Debug, PartialEq, Default, Builder, Clone)] struct Generic where T: Clone, { ipsum: &'static str, pub dolor: T, } #[derive(Debug, PartialEq, Default, Builder, Clone)] pub struct GenericReference<'a, T: 'a + Default> where T: Display, { pub bar: Option<&'a T>, } #[test] fn error_if_uninitialized() { let error = GenericBuilder::::default().build().unwrap_err(); assert_eq!(&error.to_string(), "`ipsum` must be initialized"); } #[test] fn generic_builder() { let x = GenericBuilder::default() .ipsum("Generic") .dolor(true) .build() .unwrap(); assert_eq!( x, Generic { ipsum: "Generic".into(), dolor: true, } ); } #[test] fn generic_reference_builder() { static BAR: u32 = 42; let x = GenericReferenceBuilder::<'static, u32>::default() .bar(Some(&BAR)) .build() .unwrap(); assert_eq!(x, GenericReference { bar: Some(&BAR) }); } derive_builder-0.12.0/tests/generic_with_default.rs000064400000000000000000000020251046102023000205520ustar 00000000000000#[macro_use] extern crate derive_builder; #[macro_use] extern crate pretty_assertions; /// Struct taken from `@shockham/caper` to make sure we emit the correct /// code for struct-level defaults in tandem with generics. #[derive(Builder, Clone, PartialEq)] #[builder(default)] pub struct RenderItem { /// The vertices representing this items mesh pub vertices: Vec<()>, /// Whether the item is active/should be rendered pub active: bool, /// The name of the RenderItem for lookup pub name: String, /// Tag Type for grouping similar items pub tag: T, } impl Default for RenderItem { fn default() -> Self { RenderItem { vertices: Default::default(), active: true, name: "ri".into(), tag: Default::default(), } } } #[test] fn create_with_string() { let ri: RenderItem = RenderItemBuilder::default().build().unwrap(); assert_eq!(ri.tag, ""); assert_eq!(ri.name, "ri"); assert!(ri.active); } derive_builder-0.12.0/tests/ignore/no_std.rs000064400000000000000000000037761046102023000171660ustar 00000000000000//! Compile behavior test for derive_builder on no_std. Unfortunately, this has broken //! too many times due to changes in requirements for no_std, and therefore this test //! is no longer part of the required nightly pass. // requires nightly toolchain! // // compile-flags:-C panic=abort #![no_std] #![feature(alloc, allocator_api, lang_items, start, core_intrinsics, oom)] #![allow(dead_code)] use core::intrinsics; use core::panic::PanicInfo; // Pull in the system libc library for what crt0.o likely requires. // extern crate libc; #[macro_use] extern crate derive_builder; extern crate alloc; #[derive(Builder)] #[builder(no_std)] struct IgnoreEmptyStruct {} #[derive(Builder, PartialEq, Debug)] #[builder(no_std)] struct Foo { #[builder(default)] defaulted: u32, #[builder(setter(skip), try_setter)] skipped: u32, } fn main() { let foo = FooBuilder::default() .build() .unwrap(); assert_eq!(foo, Foo { defaulted: 0, skipped: 0, }) } /////////////////////////////////////////////////////////////// // some no_std-boilerplate // from https://doc.rust-lang.org/book/no-stdlib.html /////////////////////////////////////////////////////////////// // These functions and traits are used by the compiler, but not // for a bare-bones hello world. These are normally // provided by libstd. #[lang = "eh_personality"] #[no_mangle] pub extern fn eh_personality() {} // This function may be needed based on the compilation target. #[lang = "eh_unwind_resume"] #[no_mangle] pub extern fn rust_eh_unwind_resume() { } #[panic_handler] #[no_mangle] fn panic(_info: &PanicInfo) -> ! { unsafe { intrinsics::abort() } } #[lang = "oom"] #[no_mangle] pub extern fn rust_oom(_: core::alloc::Layout) -> ! { unsafe { intrinsics::abort() } } #[allow(non_snake_case)] #[no_mangle] pub extern "C" fn _Unwind_Resume() -> ! { unsafe { intrinsics::abort() } } // Entry point for this program #[start] fn start(_argc: isize, _argv: *const *const u8) -> isize { main(); 0 } derive_builder-0.12.0/tests/lifetime.rs000064400000000000000000000007621046102023000162030ustar 00000000000000#[macro_use] extern crate pretty_assertions; #[macro_use] extern crate derive_builder; #[derive(Debug, PartialEq, Default, Builder, Clone)] struct Lorem<'a> { ipsum: &'a str, } #[test] fn error_if_uninitialized() { let error = LoremBuilder::default().build().unwrap_err(); assert_eq!(&error.to_string(), "`ipsum` must be initialized"); } #[test] fn builder_test() { let x = LoremBuilder::default().ipsum("ipsum").build().unwrap(); assert_eq!(x, Lorem { ipsum: "ipsum" }); } derive_builder-0.12.0/tests/run-pass/attributes.rs000064400000000000000000000007711046102023000203430ustar 00000000000000#[macro_use] extern crate derive_builder; /// This is a doc comment for the struct #[warn(missing_docs)] #[allow(non_snake_case, dead_code)] #[derive(Builder)] struct Lorem { /// This is a doc comment for a field field_with_doc_comment: String, #[allow(missing_docs)] undocumented: String, #[allow(non_snake_case)] CamelCase: i32, #[cfg(target_os = "macos")] mac_only: bool, #[allow(non_snake_case)] #[cfg(target_os = "linux")] LinuxOnly: (), } fn main() { } derive_builder-0.12.0/tests/run-pass/crate_alias.rs000064400000000000000000000012031046102023000204130ustar 00000000000000//! Test that an alias of derive_builder is valid in #[builder(crate = "...")] //! //! This test is imperfect, as it still passes without setting `crate = "..."`. //! This is likely because `derive_builder` is automatically present in 2018 //! without needing the extern crate line. //! //! The test will fail if an incorrect alias is used, so it adds limited value. #[macro_use] extern crate derive_builder as db; #[derive(Builder)] #[builder(crate = "db")] struct AliasedCrate { #[builder(setter(into))] lorem: String, } fn main() { AliasedCrateBuilder::default() .lorem("hello") .build() .unwrap(); } derive_builder-0.12.0/tests/run-pass/custom_error_default.rs000064400000000000000000000022151046102023000223770ustar 00000000000000//! This test ensures custom errors don't need a conversion from `UninitializedFieldError` //! if uninitialized fields are impossible. #[macro_use] extern crate derive_builder; #[derive(Default, Builder)] #[builder(default, build_fn(validate = "check_person", error = "Error"))] struct Person { name: String, age: u16, } /// An error that deliberately doesn't have `impl From`; as long /// as `PersonBuilder` uses `Person::default` then missing field errors are never possible. enum Error { UnpopularName(String), UnrealisticAge(u16), } fn check_age_realistic(age: u16) -> Result<(), Error> { if age > 150 { Err(Error::UnrealisticAge(age)) } else { Ok(()) } } fn check_name_popular(name: &str) -> Result<(), Error> { if name.starts_with('B') { Err(Error::UnpopularName(name.to_string())) } else { Ok(()) } } fn check_person(builder: &PersonBuilder) -> Result<(), Error> { if let Some(age) = &builder.age { check_age_realistic(*age)?; } if let Some(name) = &builder.name { check_name_popular(name)?; } Ok(()) } fn main() {} derive_builder-0.12.0/tests/run-pass/custom_types.rs000064400000000000000000000010251046102023000207040ustar 00000000000000#![allow(dead_code)] #[macro_use] extern crate derive_builder; struct Unit; type Clone = Unit; type Into = Unit; type Option = Unit; type Result = Unit; type Some = Unit; type String = Unit; impl core::fmt::Debug for Unit { fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { write!(f, "()") } } impl core::fmt::Display for Unit { fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { write!(f, "()") } } #[derive(Builder)] struct IgnoreEmptyStruct {} fn main() { } derive_builder-0.12.0/tests/run-pass/empty_struct.rs000064400000000000000000000001751046102023000207150ustar 00000000000000#[macro_use] extern crate derive_builder; #[allow(dead_code)] #[derive(Builder)] struct IgnoreEmptyStruct {} fn main() { } derive_builder-0.12.0/tests/run-pass/multiple_derives.rs000064400000000000000000000003111046102023000215170ustar 00000000000000#[macro_use] extern crate derive_builder; #[allow(dead_code)] #[derive(Builder)] struct Foo { lorem: bool, } #[allow(dead_code)] #[derive(Builder)] struct Bar { ipsum: bool, } fn main() { } derive_builder-0.12.0/tests/setter_custom.rs000064400000000000000000000050421046102023000173010ustar 00000000000000#[macro_use] extern crate pretty_assertions; #[macro_use] extern crate derive_builder; #[derive(Debug, PartialEq, Default, Builder, Clone)] #[builder(setter(skip = "false"), default)] struct SetterCustom { #[builder(setter(custom = "true"))] setter_custom_by_explicit_opt_in: u32, #[builder(setter(custom))] setter_custom_shorthand: u32, #[builder(setter(custom = "false"))] setter_custom_by_explicit_opt_out: u32, #[builder(setter(custom = "true"), default = "4")] setter_custom_with_explicit_default: u32, #[builder(setter(custom = "true", strip_option))] setter_custom_with_strip_option: Option, } // compile test #[allow(dead_code)] impl SetterCustomBuilder { // only possible if setter was skipped fn setter_custom_by_explicit_opt_in(&mut self) -> &mut Self { self.setter_custom_by_explicit_opt_in = Some(1); self } // only possible if setter was skipped fn setter_custom_shorthand(&mut self) -> &mut Self { self.setter_custom_shorthand = Some(2); self } // only possible if setter was skipped fn setter_custom_with_explicit_default(&mut self) -> &mut Self { self.setter_custom_with_explicit_default = Some(43); self } // only possible if setter was skipped fn setter_custom_with_strip_option(&mut self) -> &mut Self { self.setter_custom_with_strip_option = Some(Some(6)); self } } #[test] fn setter_custom_defaults() { let x: SetterCustom = SetterCustomBuilder::default().build().unwrap(); assert_eq!( x, SetterCustom { setter_custom_by_explicit_opt_in: 0, setter_custom_shorthand: 0, setter_custom_by_explicit_opt_out: 0, setter_custom_with_explicit_default: 4, setter_custom_with_strip_option: None, } ); } #[test] fn setter_custom_setters_called() { let x: SetterCustom = SetterCustomBuilder::default() .setter_custom_by_explicit_opt_in() // set to 1 .setter_custom_shorthand() // set to 2 .setter_custom_by_explicit_opt_out(42) .setter_custom_with_explicit_default() // set to 43 .setter_custom_with_strip_option() // set to 6 .build() .unwrap(); assert_eq!( x, SetterCustom { setter_custom_by_explicit_opt_in: 1, setter_custom_shorthand: 2, setter_custom_by_explicit_opt_out: 42, setter_custom_with_explicit_default: 43, setter_custom_with_strip_option: Some(6) } ); } derive_builder-0.12.0/tests/setter_extend.rs000064400000000000000000000105101046102023000172520ustar 00000000000000#[macro_use] extern crate pretty_assertions; #[macro_use] extern crate derive_builder; use std::collections::HashMap; #[derive(Debug, PartialEq, Default, Builder, Clone)] struct Lorem { #[builder(setter(each = "foo_append"))] foo: String, #[builder(setter(each = "bar"))] bars: Vec, #[builder(setter(each = "baz"))] bazes: HashMap, #[builder(setter(strip_option, each = "qux"))] quxes: Option>, #[builder(setter(strip_option, each = "quux"))] quuxes: Option>, } #[derive(Debug, PartialEq, Default, Builder, Clone)] #[builder(pattern = "mutable")] struct Ipsum { #[builder(setter(each(name = "foo_append")))] foo: String, #[builder(setter(each(name = "bar")))] bars: Vec, #[builder(setter(each(name = "baz")))] bazes: HashMap, #[builder(setter(strip_option, each = "qux"))] quxes: Option>, #[builder(setter(strip_option, each = "quux"))] quuxes: Option>, } #[derive(Debug, PartialEq, Default, Builder, Clone)] #[builder] struct Dolor { #[builder(setter(each(name = "foo_append")))] foo: String, #[builder(setter(each(name = "bar", into)))] bars: Vec, #[builder(setter(each(name = "baz")))] bazes: HashMap, } #[test] fn extend_field() { let x = LoremBuilder::default() .foo("foo".into()) .bar("bar".into()) .bar("bar bar".into()) .bar("bar bar bar".into()) .foo_append('-') .baz(("baz".into(), 1)) .baz(("bazz".into(), 2)) .baz(("bazzz".into(), 3)) .foo_append("foo") .qux("qux".into()) .qux("qux qux".into()) .quux(("quux".into(), 1)) .quux(("quuxx".into(), 2)) .build() .unwrap(); assert_eq!( x, Lorem { foo: "foo-foo".into(), bars: vec!["bar".into(), "bar bar".into(), "bar bar bar".into()], bazes: vec![("baz".into(), 1), ("bazz".into(), 2), ("bazzz".into(), 3)] .into_iter() .collect(), quxes: Some(vec!["qux".into(), "qux qux".into()]), quuxes: Some( vec![("quux".into(), 1), ("quuxx".into(), 2)] .into_iter() .collect() ), } ); } #[test] fn extend_field_into() { let x = DolorBuilder::default() .foo("foo".into()) .bar("bar") .bar("bar bar") .bar("bar bar bar") .foo_append('-') .baz(("baz".into(), 1)) .baz(("bazz".into(), 2)) .baz(("bazzz".into(), 3)) .foo_append("foo") .build() .unwrap(); assert_eq!( x, Dolor { foo: "foo-foo".into(), bars: vec!["bar".into(), "bar bar".into(), "bar bar bar".into()], bazes: vec![("baz".into(), 1), ("bazz".into(), 2), ("bazzz".into(), 3)] .into_iter() .collect(), } ); } #[test] fn extend_field_mutable() { let x = IpsumBuilder::default() .foo("foo".into()) .bar("bar".into()) .bar("bar bar".into()) .bar("bar bar bar".into()) .foo_append('-') .baz(("baz".into(), 1)) .baz(("bazz".into(), 2)) .baz(("bazzz".into(), 3)) .foo_append("foo") .qux("qux".into()) .qux("qux qux".into()) .quux(("quux".into(), 1)) .quux(("quuxx".into(), 2)) .build() .unwrap(); assert_eq!( x, Ipsum { foo: "foo-foo".into(), bars: vec!["bar".into(), "bar bar".into(), "bar bar bar".into()], bazes: vec![("baz".into(), 1), ("bazz".into(), 2), ("bazzz".into(), 3)] .into_iter() .collect(), quxes: Some(vec!["qux".into(), "qux qux".into()]), quuxes: Some( vec![("quux".into(), 1), ("quuxx".into(), 2)] .into_iter() .collect() ), } ); } #[derive(Debug, PartialEq, Default, Builder, Clone)] #[builder(setter(skip))] struct Sit { #[builder(setter(each(name = "foo")))] foos: Vec, } #[test] fn extend_field_enabled() { let x = SitBuilder::default().foo(1).foo(2).build().unwrap(); assert_eq!(x, Sit { foos: vec![1, 2] }); } derive_builder-0.12.0/tests/setter_into.rs000064400000000000000000000012061046102023000167360ustar 00000000000000#[macro_use] extern crate pretty_assertions; #[macro_use] extern crate derive_builder; #[derive(Debug, PartialEq, Default, Builder, Clone)] struct Lorem { #[builder(setter(into))] foo: String, } #[derive(Debug, PartialEq, Default, Builder, Clone)] #[builder(setter(into))] struct Ipsum { foo: u32, } #[test] fn generic_field() { let x = LoremBuilder::default().foo("foo").build().unwrap(); assert_eq!( x, Lorem { foo: "foo".to_string() } ); } #[test] fn generic_struct() { let x = IpsumBuilder::default().foo(42u8).build().unwrap(); assert_eq!(x, Ipsum { foo: 42u32 }); } derive_builder-0.12.0/tests/setter_name.rs000064400000000000000000000010561046102023000167100ustar 00000000000000#[macro_use] extern crate pretty_assertions; #[macro_use] extern crate derive_builder; #[derive(Debug, PartialEq, Default, Builder, Clone)] #[builder(setter(prefix = "with"))] struct Lorem { ipsum: &'static str, #[builder(setter(name = "foo"))] pub dolor: &'static str, } #[test] fn renamed_setter() { let x = LoremBuilder::default() .with_ipsum("ipsum") .foo("dolor") .build() .unwrap(); assert_eq!( x, Lorem { ipsum: "ipsum", dolor: "dolor", } ); } derive_builder-0.12.0/tests/setter_pattern.rs000064400000000000000000000055161046102023000174520ustar 00000000000000#[macro_use] extern crate pretty_assertions; #[macro_use] extern crate derive_builder; #[derive(Debug, PartialEq, Default, Builder, Clone)] #[builder(pattern = "immutable")] struct Lorem { immutable: u32, #[builder(pattern = "mutable")] mutable_override: u32, } #[derive(Debug, PartialEq, Default, Builder, Clone)] #[builder(pattern = "mutable")] struct Ipsum { mutable: u32, #[builder(pattern = "owned")] owned_override: u32, } #[derive(Debug, PartialEq, Default, Builder, Clone)] #[builder(pattern = "owned")] struct Dolor { #[builder(pattern = "immutable")] immutable_override: u32, owned: u32, } #[derive(Debug, PartialEq, Default, Builder, Clone)] struct Sit { default: u32, } type ImmutableSetter = fn(&T, U) -> T; type OwnedSetter = fn(T, U) -> T; type MutableSetter = fn(&mut T, U) -> &mut T; #[test] fn mutable_by_default() { // the setter must have the correct signature let mutable_setter: MutableSetter = SitBuilder::default; let mut old = ::default(); mutable_setter(&mut old, 42); assert_eq!(old.default, Some(42)); } #[test] fn mutable() { // the setter must have the correct signature let mutable_setter: MutableSetter = IpsumBuilder::mutable; let mut old = IpsumBuilder::default(); mutable_setter(&mut old, 42); assert_eq!(old.mutable, Some(42)); } #[test] fn mutable_override() { // the setter must have the correct signature let mutable_setter: MutableSetter = LoremBuilder::mutable_override; let mut old = LoremBuilder::default(); mutable_setter(&mut old, 42); assert_eq!(old.mutable_override, Some(42)); } #[test] fn immutable() { // the setter must have the correct signature let immutable_setter: ImmutableSetter = LoremBuilder::immutable; let old = LoremBuilder::default(); let new = immutable_setter(&old, 42); assert_eq!(new.immutable, Some(42)); } #[test] fn immutable_override() { // the setter must have the correct signature let immutable_setter: ImmutableSetter = DolorBuilder::immutable_override; let old = DolorBuilder::default(); let new = immutable_setter(&old, 42); assert_eq!(new.immutable_override, Some(42)); } #[test] fn owned() { // the setter must have the correct signature let owned_setter: OwnedSetter = DolorBuilder::owned; let old = DolorBuilder::default(); let new = owned_setter(old, 42); assert_eq!(new.owned, Some(42)); } #[test] fn owned_override() { // the setter must have the correct signature let owned_setter: OwnedSetter = IpsumBuilder::owned_override; let old = IpsumBuilder::default(); let new = owned_setter(old, 42); assert_eq!(new.owned_override, Some(42)); } derive_builder-0.12.0/tests/setter_prefix.rs000064400000000000000000000010701046102023000172610ustar 00000000000000#[macro_use] extern crate pretty_assertions; #[macro_use] extern crate derive_builder; #[derive(Debug, PartialEq, Default, Builder, Clone)] #[builder(setter(prefix = "with"))] struct Lorem { ipsum: &'static str, #[builder(setter(prefix = "set"))] pub dolor: &'static str, } #[test] fn prefixed_setters() { let x = LoremBuilder::default() .with_ipsum("ipsum") .set_dolor("dolor") .build() .unwrap(); assert_eq!( x, Lorem { ipsum: "ipsum", dolor: "dolor", } ); } derive_builder-0.12.0/tests/setter_strip_option.rs000064400000000000000000000026531046102023000205250ustar 00000000000000#[macro_use] extern crate pretty_assertions; #[macro_use] extern crate derive_builder; #[derive(Debug, PartialEq, Default, Builder, Clone)] struct Lorem { #[builder(setter(into))] full_opt: Option, #[builder(setter(into, strip_option))] strip_opt: Option, #[builder(setter(strip_option))] strip_opt_i32: Option, #[builder(setter(strip_option))] strip_opt_vec: Option>, } #[derive(Debug, PartialEq, Default, Builder, Clone)] #[builder(setter(into, strip_option))] struct Ipsum { foo: u32, strip_opt: Option, #[builder(default)] strip_opt_with_default: Option, } #[test] fn generic_field() { let x = LoremBuilder::default() .full_opt(Some("foo".to_string())) .strip_opt("bar") .strip_opt_i32(32) .strip_opt_vec(vec![33]) .build() .unwrap(); assert_eq!( x, Lorem { full_opt: Some("foo".to_string()), strip_opt: Some("bar".to_string()), strip_opt_i32: Some(32), strip_opt_vec: Some(vec![33]), } ); } #[test] fn generic_struct() { let x = IpsumBuilder::default() .foo(42u8) .strip_opt("bar") .build() .unwrap(); assert_eq!( x, Ipsum { foo: 42u32, strip_opt: Some("bar".to_string()), strip_opt_with_default: None, } ); } derive_builder-0.12.0/tests/setter_visibility.rs000064400000000000000000000026061046102023000201610ustar 00000000000000#[macro_use] extern crate pretty_assertions; #[macro_use] extern crate derive_builder; pub mod foo { #[derive(Debug, PartialEq, Default, Builder, Clone)] #[builder(private, setter(into))] pub struct Lorem { pub private: String, #[builder(public)] pub public: String, } #[derive(Debug, PartialEq, Default, Builder, Clone)] #[builder(public, setter(into))] pub struct Ipsum { #[builder(private)] pub private: String, pub public: String, } #[test] fn setters_same_module() { let x = LoremBuilder::default() .public("Hello") .private("world!") .build() .unwrap(); assert_eq!( x, Lorem { public: "Hello".into(), private: "world!".into(), } ); let y = IpsumBuilder::default() .public("Hello") .private("world!") .build() .unwrap(); assert_eq!( y, Ipsum { public: "Hello".into(), private: "world!".into(), } ); } } #[test] fn public_setters_foreign_module() { let error = foo::IpsumBuilder::default() .public("Hello") .build() .unwrap_err(); assert_eq!(&error.to_string(), "`private` must be initialized"); } derive_builder-0.12.0/tests/skip-setter.rs000064400000000000000000000074141046102023000166600ustar 00000000000000// https://github.com/colin-kiegel/rust-derive-builder/issues/15 #[macro_use] extern crate pretty_assertions; #[macro_use] extern crate derive_builder; #[derive(Debug, Clone, PartialEq)] struct NotDefaultable(String); fn new_notdefaultable() -> NotDefaultable { NotDefaultable("Lorem".to_string()) } #[derive(Debug, PartialEq, Default, Builder, Clone)] #[builder(setter(skip = "false"))] struct SetterOptOut { setter_present_by_explicit_default: u32, #[builder(setter(skip = "true"))] setter_skipped_by_explicit_opt_out: u32, #[builder(setter(skip))] setter_skipped_by_shorthand_opt_out: u32, #[builder(setter(skip), default = "4")] setter_skipped_with_explicit_default: u32, } #[derive(Debug, PartialEq, Default, Builder, Clone)] #[builder(setter(skip))] struct SetterOptIn { setter_skipped_by_shorthand_default: u32, #[builder(setter(skip = false))] // Should be still OK without quotes setter_present_by_explicit_opt_in: u32, #[builder(setter)] setter_present_by_shorthand_opt_in: u32, #[builder(setter(prefix = "set"))] setter_present_by_shorthand_opt_in_2: u32, } #[derive(Debug, PartialEq, Builder, Clone)] #[builder(default, setter(skip))] struct SetterOptInStructDefault { setter_skipped_with_struct_default: NotDefaultable, setter_skipped_with_type_default: u32, } #[derive(Debug, PartialEq, Builder, Clone)] #[builder(setter(into))] struct SetterOptInFieldDefault { #[builder(setter(skip), default = "new_notdefaultable()")] setter_skipped_with_field_default: NotDefaultable, #[builder(default)] setter_present_by_default: u32, } // compile test #[allow(dead_code)] impl SetterOptOut { // only possible if setter was skipped fn setter_skipped_by_explicit_opt_out() {} // only possible if setter was skipped fn setter_skipped_by_shorthand_opt_out() {} } // compile test #[allow(dead_code)] impl SetterOptIn { // only possible if setter was skipped fn setter_skipped_by_shorthand_default() {} } impl Default for SetterOptInStructDefault { fn default() -> Self { SetterOptInStructDefault { setter_skipped_with_struct_default: new_notdefaultable(), setter_skipped_with_type_default: Default::default(), } } } #[test] fn setter_opt_out() { let x: SetterOptOut = SetterOptOutBuilder::default() .setter_present_by_explicit_default(42u32) .build() .unwrap(); assert_eq!( x, SetterOptOut { setter_present_by_explicit_default: 42, setter_skipped_by_explicit_opt_out: 0, setter_skipped_by_shorthand_opt_out: 0, setter_skipped_with_explicit_default: 4, } ); } #[test] fn setter_opt_in() { let x: SetterOptIn = SetterOptInBuilder::default() .setter_present_by_explicit_opt_in(47u32) .setter_present_by_shorthand_opt_in(11u32) .set_setter_present_by_shorthand_opt_in_2(815u32) .build() .unwrap(); assert_eq!( x, SetterOptIn { setter_skipped_by_shorthand_default: 0, setter_present_by_explicit_opt_in: 47, setter_present_by_shorthand_opt_in: 11, setter_present_by_shorthand_opt_in_2: 815, } ); } #[test] fn setter_skipped_with_struct_default() { let x = SetterOptInStructDefaultBuilder::default().build().unwrap(); assert_eq!(x, SetterOptInStructDefault::default()); } #[test] fn setter_skipped_with_field_default() { let x = SetterOptInFieldDefaultBuilder::default() .build() .expect("All fields were defaulted"); assert_eq!( x, SetterOptInFieldDefault { setter_skipped_with_field_default: new_notdefaultable(), setter_present_by_default: Default::default(), } ); } derive_builder-0.12.0/tests/try_setter.rs000064400000000000000000000037121046102023000166070ustar 00000000000000#[macro_use] extern crate derive_builder; use std::convert::TryFrom; use std::net::{AddrParseError, IpAddr}; use std::str::FromStr; use std::string::ToString; #[derive(Debug, Clone, PartialEq)] pub struct MyAddr(IpAddr); impl From for MyAddr { fn from(v: IpAddr) -> Self { MyAddr(v) } } impl<'a> TryFrom<&'a str> for MyAddr { type Error = AddrParseError; fn try_from(v: &str) -> Result { Ok(MyAddr(v.parse()?)) } } #[derive(Debug, PartialEq, Builder)] #[builder(try_setter, setter(into))] struct Lorem { pub source: MyAddr, pub dest: MyAddr, } #[derive(Debug, PartialEq, Builder)] #[builder(try_setter, setter(into, prefix = "set"))] struct Ipsum { pub source: MyAddr, } fn exact_helper() -> Result { LoremBuilder::default() .source(IpAddr::from_str("1.2.3.4").unwrap()) .dest(IpAddr::from_str("0.0.0.0").unwrap()) .build() } fn try_helper() -> Result { LoremBuilder::default() .try_source("1.2.3.4") .map_err(|e| e.to_string())? .try_dest("0.0.0.0") .map_err(|e| e.to_string())? .build() } #[test] fn infallible_set() { let _ = LoremBuilder::default() .source(IpAddr::from_str("1.2.3.4").unwrap()) .dest(IpAddr::from_str("0.0.0.0").unwrap()) .build(); } #[test] fn fallible_set() { let mut builder = LoremBuilder::default(); let try_result = builder.try_source("1.2.3.4"); let built = try_result .expect("Passed well-formed address") .dest(IpAddr::from_str("0.0.0.0").unwrap()) .build() .unwrap(); assert_eq!(built, exact_helper().unwrap()); } #[test] fn with_helper() { assert_eq!(exact_helper().unwrap(), try_helper().unwrap()); } #[test] fn renamed() { IpsumBuilder::default() .try_set_source("0.0.0.0") .unwrap() .build() .expect("All fields were provided"); } derive_builder-0.12.0/tests/validation.rs000064400000000000000000000035311046102023000165340ustar 00000000000000#[macro_use] extern crate derive_builder; #[derive(Debug, Clone, Builder, PartialEq, Eq)] #[builder(build_fn(validate = "LoremBuilder::validate"))] pub struct Lorem { /// A percentile. Must be between 0 and 100. my_effort: u8, /// A percentile. Must be less than or equal to `Lorem::my_effort`. #[builder(default = "40")] their_effort: u8, /// A percentile. Must be between 0 and 100. rivals_effort: u8, } impl LoremBuilder { /// Performs bound checks. fn validate(&self) -> Result<(), String> { if let Some(ref my_effort) = self.my_effort { if *my_effort > 100 { return Err("Don't wear yourself out".to_string()); } } if let Some(ref their_effort) = self.their_effort { if *their_effort > 100 { return Err("The game has changed".to_string()); } } if let Some(ref rivals_effort) = self.rivals_effort { if *rivals_effort > 100 { return Err("Your rival is cheating".to_string()); } } Ok(()) } } #[test] fn out_of_bounds() { assert_eq!( &LoremBuilder::default() .my_effort(120) .build() .unwrap_err() .to_string(), "Don't wear yourself out" ); assert_eq!( &LoremBuilder::default() .rivals_effort(120) .build() .unwrap_err() .to_string(), "Your rival is cheating" ); } #[test] fn validation_pass() { let lorem = LoremBuilder::default() .my_effort(90) .rivals_effort(89) .build() .expect("All validations should be passing"); assert_eq!( lorem, Lorem { my_effort: 90, rivals_effort: 89, their_effort: 40, } ); }