12 stable releases
1.1.4 | Dec 28, 2022 |
---|---|
1.1.1 | Dec 27, 2022 |
#330 in Rust patterns
29 downloads per month
21KB
120 lines
mapper
This library provides a convenient derive macro for implementing mapper_api::Mapper or std::convert::Into trait and generate mapping without boilerplate.
Example
use mapper::Mapper;
fn map_account_id(account_id: &u16) -> String{
account_id.to_string()
}
#[derive(Mapper)]
#[to(Person)]
struct User{
#[to(Person, field=_name)]
pub name: String,
#[to(Person, with=map_account_id)]
pub account_id: u16,
pub age: u8
}
struct Person{
pub _name: String,
pub account_id: String,
pub age: u8
}
Disclaimer
- Macro works only on structs
- Mapper doesn't handle nested properties
Default behavior
Default behavior is to take each field of annotated struct and clone those fields in the destination struct initializer by implementing mapper_api::Mapper trait :
#[derive(Mapper)]
#[to(Person)]
struct User{
pub name: String
}
struct Person{
pub name: String
}
Generate 🔄 :
impl Mapper<Person> for User{
fn to(&self)->Person{
Person{name: self.name.clone()}
}
}
Mapping types
Two mapping types are available :
- Automatic, generate mapping for destinations specified in to struct attributes, all fields of the source are used for mapping if they are not explicitly excluded. You can't use automatic mapping if additive mapping is already used for destination and strategy
- Additive, generate mapping for destinations specified in to field attributes, only annotated fields are mapped. You can't use additive mapping if automatic mapping is already used for destination and strategy
Mapping strategies
Two mapping strategies are available :
- mapper(default), map source to destination without consuming source, generate implementation of mapper_api::Mapper
- into, map source to destination by consuming source of std::convert::Into
To struct attribute
Generate automatic mapping for specified strategies.
- You can set multiple to attribute by struct
- Specify one or multiple destination types in this attribute :
#[to(Animal, Vehicle)]
- Specify one or multiple mapping strategies in this attribute :
#[to(Animal, strategy=into, strategy=mapper)]
To field attribute
Complete automatic mapping configuration set on parent struct or provide additive mapping or exclude field from any mappings
- You can set multiple to attribute by field
- This attribute is forbidden if you use only DestinationType
DestinationType
Type of the mapping destination. Mandatory argument unless field is unconditionally excluded.
Generics
You can specify destination type with generics, these generics should be compatible with the fields of your src struct :
#[derive(Mapper)]
#[to(Person::<String, u8>)]
struct User {
name: String,
age: u8
}
struct Person<T, U> {
name: T,
age: U
}
Strategy
Trigger additive mapping for mapping destination and specified strategy e.g:
#[derive(Mapper)]
struct User(#[to(Person, strategy=into)]u16, String);
struct Person(u16);
Generate 🔄 :
impl Into<Person> for User{
fn into(self)->Person{
Person{0:self.0}
}
}
Exclude
Optional parameter, specify if the field is excluded for mapping, there is 2 kind of exclusion.
- Unconditionally exclusion, exclude field of any kind of mapping e.g :
#[derive(Mapper)]
#[to(Person)]
struct User(u16, #[to(exclude)]String);
struct Person(u16);
Generate 🔄 :
impl Mapper<Person> for User{
fn into(self)->Person{
Person{0:self.0}
}
}
- Exclusion for specific destination (⚠️ not works for additive mapping), exclude field for specific destination mapping e.g :
#[derive(Mapper)]
#[to(Person,Account, strategy=into)]
struct User(u16, #[to(Person,exclude)]String);
struct Account(u16, String);
struct Person(u16);
Generate 🔄 :
impl Into<Person> for User{
fn into(self)->Person{
Person{0:self.0}
}
}
impl Into<Account> for User{
fn into(self)->Account{
Account{0:self.0, 1: self.1}
}
}
Field
Optional parameter, target the destination type field e.g :
#[derive(Mapper)]
#[to(Person)]
struct User{
#[to(Person, field=0)
name: String
};
struct Person( String);
Generate 🔄 :
impl Mapper<Person> for User{
fn to(&self)->Person{
Person{0:self.name.clone()}
}
}
With
Optional parameter, provide a function to transform the annotated field to the destination field.
You can specify strategy used by with function as following : with(<strategy>)
if you use with without specifying strategy : with
mapper strategy will be used by default
Signature of the function should be in regards of used strategy :
- with(mapper) | with :
fn foo_mapping(val: &<src_field_type>)-><dst_field_type>
- with(into) :
fn foo_mapping(val: <src_field_type>)-><dst_field_type>
Generics
You can use generics in your function if the generic types constraint respect the source field type and destination field type :
fn gen_func<T: Display>(val: &T)->String{
val.to_string()
}
#[derive(Mapper)]
#[to(Person)]
struct User {
#[to(Person, with=gen_func)]
age: u16,
}
struct Person {
age: String,
}
License: MIT OR Apache-2.0
Dependencies
~245–700KB
~16K SLoC