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