Expand description

crates.io GitHub Actions Workflow Status docs.rs GitHub License

You are reading the documentation for derive_constructors version 1.0.0

Allows to derive multiple constructor functions and implement the From and TryFrom traits for a struct by giving simple information such as their field’s names.

Also allows to derive From for enums.

§1 The Derive macros for structs: From and TryFrom

Ref: derive_constructors_proc::From, derive_constructors_proc::TryFrom

These allow you to Derive the From and TryFrom traits where a tuple of the fields are passed to the From::from or TryFrom::try_from function, for example

#[derive(derive_constructors::From, PartialEq, Debug)]
struct CharacterInfo{
    name: String,
    age: u8,
    #[no_from]
    times_appeared: u8,
    #[no_from(4)]
    years_studied: u8
}

let character_using_from = CharacterInfo::from(("Jorge".to_string(), 23));
let expected_character = CharacterInfo { name: "Jorge".to_string(), age: 23, times_appeared: 0, years_studied: 4};
assert_eq!(character_using_from, expected_character);

§2 The Attribute Macro for structs:

Ref: derive_constructors_proc::constructor

Allows you to define a constructor function, inside the proc attribute you can customize the implementation by giving this information following attributes (Note every attribute is optional):

  • named: Name of the function, constructor functions are usually named like ‘with_name of the fields’, as calling them are quite readable, like CharacterInfo::with_name_and_age("Jorge", 23).
    Note: If this field isn’t given, instead of implementing a ‘with_*’ constructor function, it will implement the From or TryFrom trait.

  • pattern (values: [From, TryFrom], default: From):

    • When using the From pattern, the function receives fields as parameters and returns this struct with said values, this is what you’ll be looking for most of the time.
    • When using the TryFrom pattern, the functions receives types that implement Into, Into…, returning a Ok with your struct if every field could successfully be turned to your field, in case not, it will return Err with an enum telling which field couldn’t get initialized and the Error why it didn’t, see examples below for this.
  • fields (default: All fields not included in the ‘defaults’ attribute): Name of the fields you want to create your constructor for, for example: fields(age, name) could result in a function like: fn new(age: u8, name: String) -> CharacterInfo.

  • defaults: Tells how to initialize fields not covered in the fields attribute, for example defaults(years_studied(4)).
    If a field isn’t either on the fields or defaults attributes, it would count as it was initialized through Default::default, this means, the times_appeared field that hasn’t been covered will be init as 0 (since u8::default() is 0).

  • error_enum_named (Only for the TryFrom pattern): Specifies the name for the enum error that it’s returned the TryFrom function fails.

  • error_enum_metadata (Only for the TryFrom pattern): Declares the metadata for the enum error that it’s returned the TryFrom function fails, you will most likely want to write error_enum_metadata(#[derive(Debug)]) in there.

§2.1 Example 1: Empty constructor

If you just apply the constructor attribute, it will just implement the From trait where it will take a tuple formed out of all your fields, in this case, from(value: (String, u8)) -> CharacterInfo.

#[derive(Debug, PartialEq)]
#[derive_constructors::constructor]
struct CharacterInfo{
    name: String,
    age: u8,
}

let character_using_from = CharacterInfo::from(("Jorge".to_string(), 23));
let expected_character = CharacterInfo { name: "Jorge".to_string(), age: 23 };
assert_eq!(character_using_from, expected_character);

§2.2 Example 2: A ‘new’ constructor using specific fields

The following example creates a function named new(name: String, age: u8) -> CharacterInfo .

Since years_studied is specified, it will be initialized as 4, and since times_appeared is not, it will be initialized as u8::default() (which is 0).

#[derive(Debug, PartialEq)]
#[derive_constructors::constructor(named(new), fields(name, age), defaults(years_studied(4)))]
struct CharacterInfo{
    name: String,
    age: u8,
    times_appeared: u8,
    years_studied: u8
}

let character_using_from = CharacterInfo::new("Jorge".to_string(), 23);
let expected_character = CharacterInfo { name: "Jorge".to_string(), age: 23, times_appeared: 0, years_studied: 4};
assert_eq!(character_using_from, expected_character);

§2.3 Example 3: A ‘new’ constructor with the TryFrom pattern

The following example creates a function named new(name: T where String: TryFrom<T>, age: U where String: TryFrom<U>) -> Result<CharacterInfo, MyEnumError>.

Since years_studied is specified, it will be initialized as 4, and since times_appeared is not, it will be initialized as u8::default() (which is 0).

In case of an error, it returns a variant of an enum named MyEnumError, this enum is specified to derive Debug and PartialEq.

let character_using_try_from = CharacterInfo::new("Jorge", 23_u16).unwrap();
let expected_character = CharacterInfo { name: "Jorge".to_string(), age: 23, times_appeared: 0, years_studied: 4};
assert_eq!(character_using_try_from, expected_character);

let produced_error = u8::try_from(23000_u16).unwrap_err();
let forced_error_using_try_from = CharacterInfo::new("Jorge", 23000_u16).unwrap_err();
let expected_error_on_try_from = MyEnumError::AgeError(produced_error);
assert_eq!(forced_error_using_try_from, expected_error_on_try_from);

#[derive(Debug, PartialEq)]
#[derive_constructors::constructor(
    named(new),
    fields(name, age),
    defaults(years_studied(4)),
    pattern(TryFrom),
    error_enum_named(MyEnumError),
    error_enum_metadata(#[derive(Debug, PartialEq)])
)]
struct CharacterInfo{
    name: String,
    age: u8,
    times_appeared: u8,
    years_studied: u8,
}

§3 The Derive macro for enums: From

Ref: derive_constructors_proc::From

This implement the From trait for each enum by creating a From::from function on each taking every field as value, for example:

#[derive(derive_constructors::From, Debug, PartialEq)]
enum MyValue{
    StaticString(&'static str),
    Number(i32),
    Boolean(bool),
}

let scattered_values = vec![MyValue::from("Age "), MyValue::from(23), MyValue::from(", over age "), MyValue::from(true)];
let specified = vec![MyValue::StaticString("Age "), MyValue::Number(23), MyValue::StaticString(", over age "), MyValue::Boolean(true)];
assert_eq!(scattered_values, specified);

Attribute Macros§

  • Allows you to define a constructor function, inside the proc attribute you can customize the implementation by giving this information following attributes (Note every attribute is optional):

Derive Macros§

  • On structs it allows to Derive the From trait where a tuple of the fields are passed to the [From::from], for example:
  • It derives TryFrom trait where a tuple of this struct’s fields are passed to the [TryFrom::try_from] function, for example