[][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:

This example deliberately fails to compile
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:

This example deliberately fails to 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();