1 | use syn::{parse_macro_input, DeriveInput}; |
2 | |
3 | mod body_impl; |
4 | mod default_attr; |
5 | mod util; |
6 | |
7 | /// # Smart Default |
8 | /// |
9 | /// This crate provides a custom derive for `SmartDefault`. `SmartDefault` is not a real trait - |
10 | /// deriving it will actually `impl Default`. The difference from regular `#[derive(Default)]` is |
11 | /// that `#[derive(SmartDefault)]` allows you to use `#[default = "..."]` attributes to customize |
12 | /// the `::default()` method and to support `struct`s that don't have `Default` for all their |
13 | /// fields - and even `enum`s! |
14 | /// |
15 | /// # Examples |
16 | /// |
17 | /// ``` |
18 | /// use smart_default::SmartDefault; |
19 | /// |
20 | /// # fn main() { |
21 | /// #[derive(SmartDefault)] |
22 | /// # #[derive(PartialEq)] |
23 | /// # #[allow (dead_code)] |
24 | /// enum Foo { |
25 | /// Bar, |
26 | /// #[default] |
27 | /// Baz { |
28 | /// #[default = 12] |
29 | /// a: i32, |
30 | /// b: i32, |
31 | /// #[default(Some(Default::default()))] |
32 | /// c: Option<i32>, |
33 | /// #[default(_code = "vec![1, 2, 3]" )] |
34 | /// d: Vec<u32>, |
35 | /// #[default = "four" ] |
36 | /// e: String, |
37 | /// }, |
38 | /// Qux(i32), |
39 | /// } |
40 | /// |
41 | /// assert!(Foo::default() == Foo::Baz { |
42 | /// a: 12, |
43 | /// b: 0, |
44 | /// c: Some(0), |
45 | /// d: vec![1, 2, 3], |
46 | /// e: "four" .to_owned(), |
47 | /// }); |
48 | /// # } |
49 | /// ``` |
50 | /// |
51 | /// * `Baz` has the `#[default]` attribute. This means that the default `Foo` is a `Foo::Baz`. Only |
52 | /// one variant may have a `#[default]` attribute, and that attribute must have no value. |
53 | /// * `a` has a `#[default = 12]` attribute. This means that it's default value is `12`. |
54 | /// * `b` has no `#[default = ...]` attribute. It's default value will `i32`'s default value |
55 | /// instead - `0`. |
56 | /// * `c` is an `Option<i32>`, and it's default is `Some(Default::default())`. Rust cannot (currently) |
57 | /// parse `#[default = Some(Default::default())]` and therefore we have to use a special syntax: |
58 | /// `#[default(Some(Default::default))]` |
59 | /// * `d` has the `!` token in it, which cannot (currently) be parsed even with `#[default(...)]`, |
60 | /// so we have to encode it as a string and mark it as `_code = `. |
61 | /// * `e` is a `String`, so the string literal "four" is automatically converted to it. This |
62 | /// automatic conversion **only** happens to string (or byte string) literals - and only if |
63 | /// `_code` is not used. |
64 | /// * Documentation for the `impl Default` section is generated automatically, specifying the |
65 | /// default value returned from `::default()`. |
66 | #[proc_macro_derive (SmartDefault, attributes(default))] |
67 | pub fn derive_smart_default(input: proc_macro::TokenStream) -> proc_macro::TokenStream { |
68 | let input: DeriveInput = parse_macro_input!(input as DeriveInput); |
69 | match body_impl::impl_my_derive(&input) { |
70 | Ok(output: TokenStream) => output.into(), |
71 | Err(error: Error) => error.to_compile_error().into(), |
72 | } |
73 | } |
74 | |