#derive #new #enum #constructor #argument

macro derive-new

#[derive(new)] implements simple constructor functions for structs and enums

16 releases

0.5.8 Aug 18, 2019
0.5.7 Jul 11, 2019
0.5.6 Nov 3, 2018
0.5.5 Jul 12, 2018
0.3.0 Nov 19, 2016
Download history 15205/week @ 2019-06-21 9557/week @ 2019-06-28 9902/week @ 2019-07-05 9823/week @ 2019-07-12 9643/week @ 2019-07-19 11277/week @ 2019-07-26 10070/week @ 2019-08-02 10980/week @ 2019-08-09 11279/week @ 2019-08-16 14046/week @ 2019-08-23 13061/week @ 2019-08-30 13477/week @ 2019-09-06 13017/week @ 2019-09-13 13673/week @ 2019-09-20 14645/week @ 2019-09-27

49,282 downloads per month
Used in 129 crates (55 directly)

MIT license

18KB
322 lines

A custom derive implementation for #[derive(new)]

A derive(new) attribute creates a new constructor function for the annotated type. That function takes an argument for each field in the type giving a trivial constructor. This is useful since as your type evolves you can make the constructor non-trivial (and add or remove fields) without changing client code (i.e., without breaking backwards compatibility). It is also the most succinct way to initialise a struct or an enum.

Implementation uses macros 1.1 custom derive (which works in stable Rust from 1.15 onwards).

#[no_std] is fully supported if you switch off the default feature "std".

Examples

Cargo.toml:

[dependencies]
derive-new = "0.5"

Include the macro:

#[macro_use]
extern crate derive_new;

Generating constructor for a simple struct:

#[derive(new)]
struct Bar {
    a: i32,
    b: String,
}

let _ = Bar::new(42, "Hello".to_owned());

Default values can be specified either via #[new(default)] attribute which removes the argument from the constructor and populates the field with Default::default(), or via #[new(value = "..")] which initializes the field with a given expression:

#[derive(new)]
struct Foo {
    x: bool,
    #[new(value = "42")]
    y: i32,
    #[new(default)]
    z: Vec<String>,
}

let _ = Foo::new(true);

Generic types are supported; in particular, PhantomData<T> fields will be not included in the argument list and will be intialized automatically:

use std::marker::PhantomData;

#[derive(new)]
struct Generic<'a, T: Default, P> {
    x: &'a str,
    y: PhantomData<P>,
    #[new(default)]
    z: T,
}

let _ = Generic::<i32, u8>::new("Hello");

For enums, one constructor method is generated for each variant, with the type name being converted to snake case; otherwise, all features supported for structs work for enum variants as well:

#[derive(new)]
struct Enum {
    FirstVariant,
    SecondVariant(bool, #[new(default)] u8),
    ThirdVariant { x: i32, #[new(value = "vec![1]")] y: Vec<u8> }
}

let _ = Enum::new_first_variant();
let _ = Enum::new_second_variant(true);
let _ = Enum::new_third_variant(42);

Dependencies

~0.6–0.9MB
~20K SLoC