model_mapper_macros/lib.rs
1mod input;
2mod model_mapper;
3
4use proc_macro::TokenStream;
5use proc_macro_error2::proc_macro_error;
6
7/// Derive mapper functions to convert between types.
8///
9/// A `mapper` attribute is required at type-level and it's optional at field or variant level.
10///
11/// The following attributes are available:
12///
13/// #### Type level attributes
14///
15/// - `ty = PathType` _(**mandatory**)_: The other type to derive the conversion
16/// - `from` _(optional)_: Whether to derive `From` the other type for self
17/// - `custom` _(optional)_: Derive a custom function instead of the trait
18/// - `custom = from_other` _(optional)_: Derive a custom function instead of the trait, with the given name
19/// - `into` _(optional)_: Whether to derive `From` self for the other type
20/// - `custom` _(optional)_: Derive a custom function instead of the trait
21/// - `custom = from_other` _(optional)_: Derive a custom function instead of the trait, with the given name
22/// - `try_from` _(optional)_: Whether to derive `TryFrom` the other type for self
23/// - `custom` _(optional)_: Derive a custom function instead of the trait
24/// - `custom = from_other` _(optional)_: Derive a custom function instead of the trait, with the given name
25/// - `try_into` _(optional)_: Whether to derive `TryFrom` self for the other type
26/// - `custom` _(optional)_: Derive a custom function instead of the trait
27/// - `custom = from_other` _(optional)_: Derive a custom function instead of the trait, with the given name
28/// - `add` _(optional, multiple)_: Additional fields (for structs with named fields) or variants (for enums) the other
29/// type has and this one doesn't **¹**
30/// - `field = other_field` _(mandatory)_: The field or variant name
31/// - `ty = bool` _(optional)_: The field type, mandatory for `into` and `try_into` if no default value is provided
32/// - `default` _(optional)_: The field or variant will be populated using `Default::default()` (mandatory for enums,
33/// with or without value)
34/// - `value = true` _(optional)_: The field or variant will be populated with the given expression instead
35/// - `ignore_extra` _(optional)_: Whether to ignore all extra fields (for structs) or variants (for enums) of the other
36/// type **²**
37///
38/// #### Variant level attributes
39///
40/// - `rename = OtherVariant` _(optional)_: To rename this variant on the other enum
41/// - `add` _(optional, multiple)_: Additional fields of the variant that the other type variant has and this one
42/// doesn't **¹**
43/// - `field = other_field` _(mandatory)_: The field name
44/// - `ty = bool` _(optional)_: The field type, mandatory for `into` and `try_into` if no default value is provided
45/// - `default` _(optional)_: The field or variant will be populated using `Default::default()`
46/// - `value = true` _(optional)_: The field or variant will be populated with the given expression instead
47/// - `skip` _(optional)_: Whether to skip this variant because the other enum doesn't have it
48/// - `default` _(mandatory)_: The field or variant will be populated using `Default::default()`
49/// - `value = get_default_value()` _(optional)_: The field or variant will be populated with the given expression
50/// instead
51/// - `ignore_extra` _(optional)_: Whether to ignore all extra fields of the other variant (only valid for _from_ and
52/// _try_from_) **²**
53///
54/// #### Field level attributes
55///
56/// - `rename = other_name` _(optional)_: To rename this field on the other type
57/// - `skip` _(optional)_: Whether to skip this field because the other type doesn't have it
58/// - `default` _(optional)_: The field or variant will be populated using `Default::default()`
59/// - `value = get_default_value()` _(optional)_: The field or variant will be populated with the given expression
60/// instead
61///
62/// Additional hints on how to map fields:
63///
64/// - `opt` _(optional)_: The field is an `Option` and the inner value shall be mapped **³**
65/// - `iter` _(optional)_: The field is an iterator and the inner value shall be mapped **³**
66/// - `map` _(optional)_: The field is a hashmap-like iterator and the inner value shall be mapped **³**
67/// - `with = mod::my_function` _(optional)_: If the field type doesn't implement `Into` or `TryInto` the other, this
68/// property allows you to customize the behavior by providing a conversion function
69/// - `from_with = mod::my_function` _(optional)_: The same as above but only for the `from` or `try_from` derives
70/// - `from_with = mod::my_function` _(optional)_: The same as above but only for the `from` or `try_from` derives
71///
72/// **¹** When providing additional fields without defaults, the `From` and `TryFrom` traits can't be derived and
73/// a custom function will be required instead. When deriving `into` or `try_into`, the `ty` must be provided as well.
74///
75/// **²** When ignoring fields or variants it might be required that the enum or the struct implements `Default`
76/// in order to properly populate it.
77///
78/// **³** Hints can be nested, for example: `opt(vec)`, `vec(opt(with = "my_custom_fn"))`
79///
80/// ## Example
81///
82/// ```rs
83/// #[derive(Mapper)]
84/// #[mapper(from, ty = Entity)]
85/// pub struct Model {
86/// id: i64,
87/// name: String,
88/// #[mapper(skip(default))]
89/// surname: Option<String>,
90/// }
91/// ```
92///
93/// Other advanced use cases are available on the [examples folder](https://github.com/lasantosr/model-mapper/tree/main/model-mapper/examples/).
94#[proc_macro_error]
95#[proc_macro_derive(Mapper, attributes(mapper))]
96pub fn model_mapper(input: TokenStream) -> TokenStream {
97 let input = syn::parse_macro_input!(input as syn::DeriveInput);
98 model_mapper::r#impl(input).into()
99}