[−][src]Attribute Macro scones::make_builder
#[make_builder]
Proc macro to generate builders for structs.
It is recommended to read the documentation of #[make_constructor]
before reading this.
Basic Usage
The simplest way to use this macro is without any additional arguments:
use scones::make_builder; #[make_builder] struct MyStruct { int: i32, string: String, } let instance = MyStructBuilder::new() .int(10) .string("Hello World".to_owned()) .build();
Syntax
The full syntax of this macro is as follows:
#[make_builder(visibility name params return_type)]
Each of these elements are optional but must always be present in the order listed above. If an element is omitted, a default value is used instead. Invoking the macro without any of the arguments listed above is equivalent to:
#[make_builder(pub <StructName>Builder(..) -> Self)]
To make the visibility of the generated builder blank, provide a name but no visibility, like so:
#[make_builder(PrivateBuilder)]
Params
This argument can be used to provide additional parameters or make parameters optional. It is a comma-seperated list of parameters enclosed in parenthesis. To add an extra parameter (I.E. one which does not correspond to a field in your struct), use Rust's regular function parameter syntax:
#[make_builder((custom_param: i32))]
By default, this parameter will be required, meaning code that uses your builder will not
compile if it does not set a value for custom_param
. If you want to make it optional, make
the type Option<_>
. Note that the the macro is expecting the literal text Option
, you
cannot use a type alias.
#[make_builder((optional: Option<i32>))]
Override fields can be specified with the following syntax, more on what this means later:
#[make_builder((field_name?))]
Return Type
The return type can either be -> Self
or -> Result<Self, [any type]>
. Note that the macro
is expecting the literal text Self
and/or Result
, it is not capable of recognizing type
aliases like std::fmt::Result
. Here is an example of how to make a builder that can return
an error:
#[make_builder(-> Result<Self, FileError>)]
Value Attributes
You can use the #[value()]
attribute to add custom code for initializing a field:
use scones::make_builder; #[make_builder] struct MyStruct { #[value(123)] data: i32 } // We no longer need to specify a value for `data`. let instance = MyStructBuilder::new().build();
You can place any expression inside the parenthesis. Keep in mind that fields are initialized in the order you declare them, so take care not to use parameters after they are moved:
use scones::make_builder; #[make_builder] struct MyStruct { field_0: String, #[value(field_0.clone())] field_1: String, }
You can make a value attribute only apply to a certain builder by appending
for BuilderName
to the end. You can do this multiple times for a single field of your
struct. If you have a value attribute without a for
clause and multiple value attributes with
for
clauses on the same field, the one without the clause will be used as a default for
whenever there is not a specific value attribute for a particular builder:
use scones::make_builder; #[make_builder(DefaultBuilder)] #[make_builder(SpecificBuilder)] struct MyStruct { #[value(0)] #[value(31415 for SpecificBuilder)] data: i32, } let data_is_zero = DefaultBuilder::new().build(); let data_is_31415 = SpecificBuilder::new().build();
When a field has a value attribute, the macro will not automatically add it to the parameters for the builder. If you still want it to be a parameter despite this, you can explicitly add it back to the parameter list of the builder:
use scones::make_builder; #[make_builder((data))] struct MyStruct { #[value(data + 2)] data: i32 } let data_is_10 = MyStructBuilder::new().data(8).build();
Required, Optional, and Override parameters
By default, all parameters for a builder are required. This means that the following code will not compile:
use scones::make_builder; #[make_builder] struct MyStruct { data: i32 } // Ok let instance = MyStructBuilder::new().data(0).build(); // Compile error! ("build() does not exist on type MyStructBuilder<Missing>") let instance = MyStructBuilder::new().build();
As mentioned before, you can add a parameter and explicitly give it an Option<>
datatype
to make it optional, in which case it does not matter whether or not you specify its value
when using the builder, your code will still compile. One common use of this is to have a
default value for a particular field, but allow a user to change it. The long way to do that
would be as follows:
use scones::make_builder; #[make_builder((data: Option<i32>))] struct MyStruct { #[value(data.unwrap_or(100))] data: i32 }
However, the case shown above is a fairly common and straightforward pattern, so the following shortcut was created which produces identical results:
use scones::make_builder; #[make_builder((data?))] struct MyStruct { #[value(100)] data: i32 }
The usage of data?
is called an "override" because it is not required, but when it is
provided, it will override the default value of data
.
Templates and Tuple Structs
All the above semantics work with templated structs:
use scones::make_builder; #[make_builder] // This also works with `where T: ToString`. struct MyStruct<T: ToString> { #[value(data.to_string())] text: String, data: T, }; let instance = MyStructBuilder::new().data(123).build();
All the above semantics are supported with tuple structs as well, the only difference being that
fields are given the names field_0
, field_1
, etc.
use scones::make_builder; #[make_builder] struct MyTuple( i32, #[value(field_0)] i32, ); let instance = MyTupleBuilder::new().field_0(123).build();