[][src]Attribute Macro scones::make_constructor

#[make_constructor]

Proc macro to generate constructors for structs.

Basic Usage

The simplest way to use this macro is without any additional arguments:

use scones::make_constructor;

#[make_constructor]
struct MyStruct {
    int: i32,
    string: String,
}

// The macro generates:
// impl MyStruct {
//     pub fn new(int: i32, string: String) -> Self {
//         Self {
//             int,
//             string,
//         }
//     }
// }

Syntax

The full syntax of this macro is as follows:

#[make_constructor(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_constructor(pub new(..) -> Self)]

To make the visibility of the generated function blank, provide a name but no visibility, like so:

#[make_constructor(private_new)]

Params

This argument can be used to rearrange the order of generated parameters or provide additional parameters. It is a comma-seperated list of parameters enclosed in parenthesis. To specify the location of a parameter for a particular field, use the name of that field:

#[make_constructor((second_field, first_field))]

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_constructor((field, custom_param: i32))]

You can also use ellipses to specify where any other required parameters should be inserted. If the macro detects that you have not explicitly given a position for a required parameter, it will insert them wherever you place the ellipses:

// Generates `pub fn new(field_a, field_b, custom_param) -> Self`.
#[make_constructor((.., custom_param: i32))]

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 constructor that can return an error:

#[make_constructor(-> Result<Self, FileError>)]

Value Attributes

You can use the #[value()] attribute to add custom code for initializing a field:

use scones::make_constructor;

#[make_constructor]
struct MyStruct {
    #[value(123)]
    data: i32
}

// The macro generates:
// impl MyStruct {
//     fn new() -> Self {
//         Self {
//             data: 123,
//         }
//     }
// }

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_constructor;

#[make_constructor]
struct MyStruct {
    field_0: String,
    #[value(field_0.clone())]
    field_1: String,
}

// The macro generates:
impl MyStruct {
    pub fn new(field_0: String) -> Self {
        Self {
            field_0: field_0,
            field_1: field_0.clone()
        }
    }
}

You can make a value attribute only apply to a certain constructor by appending for constructor_name 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 constructor:

use scones::make_constructor;

#[make_constructor(default)]
#[make_constructor(specific)]
struct MyStruct {
    #[value(0)]
    #[value(31415 for specific)]
    data: i32,
}

// The macro generates:
// impl MyStruct {
//     pub fn default() -> Self {
//         Self { data: 0 }
//     }
//     pub fn specific() -> Self {
//         Self { data: 31415 }
//     }
// }

When a field has a value attribute, the macro will not automatically add it to the parameters for the constructor. If you still want it to be a parameter despite this, you can explicitly add it back to the parameter list of the constructor:

use scones::make_constructor;

#[make_constructor((data))]
struct MyStruct {
    #[value(data + 2)]
    data: i32
}

// The macro generates:
// impl MyStruct {
//     pub fn new(data: i32) -> Self {
//         Self { data: data + 2 }
//     }
// }

Templates and Tuple Structs

All the above semantics work with templated structs:

use scones::make_constructor;

#[make_constructor]
// This also works with `where T: ToString`.
struct MyStruct<T: ToString> {
    #[value(data.to_string())]
    text: String,
    data: T,
};

// The macro generates:
// impl<T: ToString> MyTuple<T> {
//     pub fn new(data: T) -> Self {
//         Self {
//             text: data.to_string(),
//             data: data,
//         }
//     }
// }

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_constructor;

#[make_constructor]
struct MyTuple(
    i32,
    #[value(field_0)] i32,
);

// The macro generates:
// impl MyTuple {
//     pub fn new(field_0: i32) -> Self {
//         Self(field_0, field_0)
//     }
// }