derive-ctor 0.1.0

Adds `#[derive(ctor)]` which allows for the auto-generation of a constructor.
Documentation

derive-ctor

derive-ctor is a Rust procedural macro crate that allows you to easily generate constructor methods for your structs. With the #[derive(ctor)] attribute, you can automatically create a constructor for all fields in the struct. The crate also provides various options to customize the generated constructor methods.

Features

  • Automatically generate a constructor method for all fields in a struct with #[derive(ctor)].
  • Customize the name and visibility of the auto-generated constructor using #[ctor(visibility method_name)].
  • Provide a list of names to generate multiple constructors.
  • Customize field behavior in the constructor with the following attributes:
    • #[ctor(default)] - Exclude the field from the generated method and use its default value.
    • #[ctor(value(EXPRESSION))] - Exclude the field from the generated method and use the defined expression as its default value.
    • #[ctor(method(METHOD_NAME))] - Exclude the field from the generated method and call the defined method for its default value.
    • #[ctor(impl)] - Change the parameter type for the generated method to impl Into<Type>.

Basic Usage

Add derive-ctor to your Cargo.toml:

[dependencies]

derive-ctor = "0.1"

Import the crate in your Rust code:

use derive_ctor::ctor;

Annotate your struct with #[derive(ctor)] to automatically generate a new constructor:

#[derive(ctor)]
struct MyStruct {
    field1: i32,
    field2: String
}

let my_struct = MyStruct::new(1, String::from("Foo"));

Configurations

You can modify the name and visibility of the generated method, and define additional constructors by using the #[ctor] attribute on the target struct after ctor is derived.

In the following example, three constructor methods are created: new, with_defaults, and internal. These methods all inherit their respective visibilities defined within the #[ctor] attribute.

#[derive(ctor)]
#[ctor(pub new, pub(crate) with_defaults, internal)]
struct MyStruct {
    field1: i32,
    field2: String
}

Field Configurations

Fields can also be annotated with #[ctor(PROPERTY)] to change their behaviour in the generated methods. The following are the available properties that can be used with the field-attributes

#[ctor(default)] - This property excludes the annotated field from the constructor and uses its default value.

#[derive(ctor)]
struct MyStruct {
    field1: i32,
    #[ctor(default)]
    field2: String
}

let my_struct = MyStruct::new(100);

#[ctor(impl)] - This property modifies the parameter type of the annotated field for the generated method converting it from Type -> impl Into<Type>.

#[derive(ctor)]
struct MyStruct {
    field1: i32,
    #[ctor(impl)] // the parameter type will now be impl Into<String> instead of String
    field2: String
}

let my_struct = MyStruct::new(100, "Foo");

#[ctor(value(VALUE))] - This property excludes the annotated field from the constructor and utilizes the defined expression to generate its value.

#[derive(ctor)]
struct MyStruct {
    field1: i32,
    #[ctor(value(String::from("Foo")))]
    field2: String
}

let my_struct = MyStruct::new(100); // generates MyStruct { field1: 100, field2: "foo" }

#[ctor(method(METHOD_NAME)] - This property exludes the annotated field from the constructor and invokes the provided method to generate its value.

fn generate_struct_value() -> String {
    String::from("Foo")
}

#[derive(ctor)]
struct MyStruct {
    field1: i32,
    #[ctor(method(generate_struct_value))]
    field2: String
}

let my_struct = MyStruct::new(100);

Advanced Configuration

Field attributes can additionally be configured with a list of indices corresponding to the methods to use the generated value for. This allows for the creation of multiple functions with different parameter requirements.

#[derive(ctor)]
#[ctor(new, with_defaults)]
struct MyStruct {
    field1: i32,
    #[ctor(default) = [1]]
    field2: String,
    #[ctor(default) = 1] // brackets can be removed if specifying only 1 index
    field3: bool,
    #[ctor(default) = [0, 1]]
    field4: u64,
    #[ctor(default)] // this is the same as specifying all indices
    field5: u64
}

let my_struct1 = MyStruct::new(100, "Foo".to_string(), true);
let my_struct2 = MyStruct::with_defaults(100);