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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
//! # Model Mapper
//!
//! A powerful Rust macro to generate boilerplate-free declarations of `From`, `Into`, `TryFrom`, and `TryInto` traits
//! for converting between structs and enums.
//!
//! It is designed to handle common patterns like detailed DTOs to internal entities, handling optional fields, nested
//! collections, and even disparate generic types.
//!
//! ## Features
//!
//! - **Zero Boilerplate**: Automatically implements `From`, `Into`, `TryFrom`, and `TryInto`.
//! - **Flexible Mapping**: Handle renamed fields, skipped fields, and additional fields.
//! - **Custom Logic**: Inject custom conversion logic for specific fields using functions or expressions.
//! - **Generics Support**: Seamless mapping between generic types with different parameters.
//! - **Multiple Targets**: Map a single type to multiple other types with conditional configurations.
//! - **Nested Mapping**: Built-in support for mapping inner values within Option, iterators, and maps.
//! - **`no_std` compatible**: Works in `no_std` environments (with default features disabled).
//!
//! ## Quick Start
//!
//! The most common use case is mapping between domain entities and DTOs.
//!
//! ```rust
//! # use model_mapper::Mapper;
//! # struct Entity {
//! # id: i64,
//! # name: String,
//! # }
//! #[derive(Mapper)]
//! #[mapper(from, ty = Entity)]
//! pub struct Model {
//! id: i64,
//! name: String,
//! }
//! ```
//!
//! The macro expansion above would generate something like:
//!
//! ```rust
//! # struct Entity { id: i64, name: String }
//! # struct Model { id: i64, name: String }
//! impl From<Entity> for Model {
//! fn from(Entity { id, name }: Entity) -> Self {
//! Self {
//! id: Into::into(id),
//! name: Into::into(name),
//! }
//! }
//! }
//! ```
//!
//! Because types doesn't always fit like a glove, you can provide additional fields on runtime, at the cost of not
//! being able to use the `From` trait:
//!
//! ```rust
//! # use model_mapper::Mapper;
//! pub mod service {
//! pub struct UpdateUserInput {
//! pub user_id: i64,
//! pub name: Option<String>,
//! pub surname: Option<String>,
//! }
//! }
//!
//! #[derive(Mapper)]
//! #[mapper(
//! into(custom = "into_update_user"),
//! ty = service::UpdateUserInput,
//! add(field = user_id, ty = i64),
//! add(field = surname, default(value = None))
//! )]
//! pub struct UpdateProfileRequest {
//! pub name: String,
//! }
//! ```
//!
//! Would generate something like:
//!
//! ```rust
//! # pub mod service {
//! # pub struct UpdateUserInput {
//! # pub user_id: i64,
//! # pub name: Option<String>,
//! # pub surname: Option<String>,
//! # }
//! # }
//! # struct UpdateProfileRequest { name: String }
//! impl UpdateProfileRequest {
//! /// Builds a new [service::UpdateUserInput] from a [UpdateProfileRequest]
//! pub fn into_update_user(self, user_id: i64) -> service::UpdateUserInput {
//! let UpdateProfileRequest { name } = self;
//! service::UpdateUserInput {
//! user_id,
//! surname: None,
//! name: Into::into(name),
//! }
//! }
//! }
//! ```
//!
//! Other advanced use cases are available on the [examples folder](https://github.com/lasantosr/model-mapper/tree/main/model-mapper/examples/).
//!
//! ## Detailed Usage
//!
//! 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
//! - `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
//! - `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
//! - `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
//! - `into_with = mod::my_function` _(optional)_: The same as above but only for the `into` or `try_into` derives
//! - `from_with = mod::my_function` _(optional)_: The same as above but only for the `from` or `try_from` derives
//!
//! - 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 **³**
//! - `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"))`
//!
//! ### Multiple derives
//!
//! When deriving conversions for a single type, attributes can be set directly:
//!
//! ```rust-ignore
//! #[mapper(from, into, ty = OtherType, add(field = field_1, default), add(field = field_2, default))]
//! struct MyStruct;
//! ```
//!
//! But we can also derive conversions for multiple types by wrapping the properties on a `derive` attribute:
//!
//! ```rust-ignore
//! #[mapper(derive(try_into, ty = OtherType, add(field = field_1, default)))]
//! #[mapper(derive(from, ty = YetAnotherType))]
//! struct MyStruct;
//! ```
//!
//! If multiple conversions are involved, both variant and field level attributes can also be wrapped in a `when`
//! attribute and must set the `ty` they refer to:
//!
//! ```rust-ignore
//! #[mapper(when(ty = OtherType, with = ToString::to_string))]
//! #[mapper(when(ty = YetAnotherType, skip(default)))]
//! struct MyStruct;
//! ```
// Re-export derive macro crate
extern crate model_mapper_macros;
pub use *;