smart_default/
lib.rs

1use syn::{parse_macro_input, DeriveInput};
2
3mod body_impl;
4mod default_attr;
5mod 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))]
67pub fn derive_smart_default(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
68    let input = parse_macro_input!(input as DeriveInput);
69    match body_impl::impl_my_derive(&input) {
70        Ok(output) => output.into(),
71        Err(error) => error.to_compile_error().into(),
72    }
73}