model-mapper 0.7.1

Derive macro to map between different types
Documentation
//! # 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 **&#xb9;**
//!     - `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 **&#xb2;**
//!
//! - 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 **&#xb9;**
//!     - `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_) **&#xb2;**
//!
//! - 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 **&#xb3;**
//!   - `iter` _(optional)_: The field is an iterator and the inner value shall be mapped **&#xb3;**
//!   - `map` _(optional)_: The field is a hashmap-like iterator and the inner value shall be mapped **&#xb3;**
//!   - `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
//!
//! **&#xb9;** 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.
//!
//! **&#xb2;** When ignoring fields or variants it might be required that the enum or the struct implements `Default`
//! in order to properly populate it.
//!
//! **&#xb3;** 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;
//! ```

#![cfg_attr(not(feature = "std"), no_std)]

// Re-export derive macro crate
#[allow(unused_imports)]
#[macro_use]
extern crate model_mapper_macros;
#[doc(hidden)]
pub use model_mapper_macros::*;

#[doc(hidden)]
pub mod private {
    pub trait RefMapper<T, R> {
        fn map_value(&self, arg: T) -> R;
    }
    impl<F, T, R> RefMapper<T, R> for F
    where
        F: ?Sized + Fn(&T) -> R,
    {
        #[inline(always)]
        fn map_value(&self, arg: T) -> R {
            (self)(&arg)
        }
    }

    pub trait ValueMapper<T, R> {
        fn map_value(&self, arg: T) -> R;
    }
    impl<F, T, R> ValueMapper<T, R> for &F
    where
        F: ?Sized + Fn(T) -> R,
    {
        #[inline(always)]
        fn map_value(&self, arg: T) -> R {
            (*self)(arg)
        }
    }
}