]>
Commit | Line | Data |
---|---|---|
f20569fa XL |
1 | # A custom derive implementation for `#[derive(new)]` |
2 | ||
3 | A `derive(new)` attribute creates a `new` constructor function for the annotated | |
4 | type. That function takes an argument for each field in the type giving a | |
5 | trivial constructor. This is useful since as your type evolves you can make the | |
6 | constructor non-trivial (and add or remove fields) without changing client code | |
7 | (i.e., without breaking backwards compatibility). It is also the most succinct | |
8 | way to initialise a struct or an enum. | |
9 | ||
10 | Implementation uses macros 1.1 custom derive (which works in stable Rust from | |
11 | 1.15 onwards). | |
12 | ||
13 | `#[no_std]` is fully supported if you switch off the default feature `"std"`. | |
14 | ||
15 | ## Examples | |
16 | ||
17 | Cargo.toml: | |
18 | ||
19 | ```toml | |
20 | [dependencies] | |
21 | derive-new = "0.5" | |
22 | ``` | |
23 | ||
24 | Include the macro: | |
25 | ||
26 | ```rust | |
27 | #[macro_use] | |
28 | extern crate derive_new; | |
29 | ``` | |
30 | ||
31 | Generating constructor for a simple struct: | |
32 | ||
33 | ```rust | |
34 | #[derive(new)] | |
35 | struct Bar { | |
36 | a: i32, | |
37 | b: String, | |
38 | } | |
39 | ||
40 | let _ = Bar::new(42, "Hello".to_owned()); | |
41 | ``` | |
42 | ||
43 | Default values can be specified either via `#[new(default)]` attribute which removes | |
44 | the argument from the constructor and populates the field with `Default::default()`, | |
45 | or via `#[new(value = "..")]` which initializes the field with a given expression: | |
46 | ||
47 | ```rust | |
48 | #[derive(new)] | |
49 | struct Foo { | |
50 | x: bool, | |
51 | #[new(value = "42")] | |
52 | y: i32, | |
53 | #[new(default)] | |
54 | z: Vec<String>, | |
55 | } | |
56 | ||
57 | let _ = Foo::new(true); | |
58 | ``` | |
59 | ||
60 | Generic types are supported; in particular, `PhantomData<T>` fields will be not | |
61 | included in the argument list and will be intialized automatically: | |
62 | ||
63 | ```rust | |
64 | use std::marker::PhantomData; | |
65 | ||
66 | #[derive(new)] | |
67 | struct Generic<'a, T: Default, P> { | |
68 | x: &'a str, | |
69 | y: PhantomData<P>, | |
70 | #[new(default)] | |
71 | z: T, | |
72 | } | |
73 | ||
74 | let _ = Generic::<i32, u8>::new("Hello"); | |
75 | ``` | |
76 | ||
77 | For enums, one constructor method is generated for each variant, with the type | |
78 | name being converted to snake case; otherwise, all features supported for | |
79 | structs work for enum variants as well: | |
80 | ||
81 | ```rust | |
82 | #[derive(new)] | |
83 | struct Enum { | |
84 | FirstVariant, | |
85 | SecondVariant(bool, #[new(default)] u8), | |
86 | ThirdVariant { x: i32, #[new(value = "vec![1]")] y: Vec<u8> } | |
87 | } | |
88 | ||
89 | let _ = Enum::new_first_variant(); | |
90 | let _ = Enum::new_second_variant(true); | |
91 | let _ = Enum::new_third_variant(42); | |
92 | ``` |