2 releases
0.1.1 | Feb 5, 2024 |
---|---|
0.1.0 | Feb 4, 2024 |
#1867 in Rust patterns
10KB
89 lines
Context Mapper
Single rust macro for generating different maps
Links
Example
#[derive(ContextMapper)]
#[context_mapper(
impl(
context = info::general
converter = MyConv::to_info,
type = info::Info,
fn = general_info
vis = pub(crate)
),
function(
context = info::all
converter = MyConv::to_info,
type = info::Info,
fn = all_info
),
)]
struct Person {
name: String,
address: info::Address,
age: usize,
/// Let's hide it for the geneal info, but show for the rest
#[context_attribute(context(name=info::general, skip))]
is_a_reptile: bool
}
// …
let person = Person {
//…
};
person.general_info();
all_info(&person);
lib.rs
:
Universal library for struct mapping. Provides multiple methods to generate HashMaps with values of any type
Example problem
Let's assume that we've got this struct
struct Person {
name: String
/// Age in years
age: usize,
/// Dept in $ in the certain banks
dept: BTreeMap<String, f64>,
/// Amount of money in banks. Accounts in $
bank_account: BTreeMap<String, f64>,
/// Amount of money in the wallet in $
wallet: f64,
/// Amount of money in the crypto in crypto-wallets. Transformed to $
crypto: BTreeMap<String, f64>
}
Now, we want to get a few info:
avg(&self) -> HashMap<String, f64>
returning average amount of money in every fieldmax(&self) -> HashMap<String, f64>
returning max amount of money in every fieldinfo(&self) -> HashMap<String, String>
returning general information about fieldsdetail_info(&self) -> HashMap<String, String>
. Similar to 3, but with more info
We would need to implement it manually. It's cumbersome and inconvinient. That's where
context_mapper
becomes a handy tool:
#[derive(ContextMapper)]
// F64 traits
#[context_mapper(
trait(
context = p01::average,
type = f64,
converter = MyAvgTrait::avg,
generic(
name = Averager,
method_name = avg
)
),
trait(
context = p02::max,
type = f64,
converter = MyMaxTrait::max,
simple(
name = Maximizer,
method_name = max
)
)
)]
// String traits
#[context_mapper(
trait(
context = p03::general,
type = String,
converter = std::string::ToString::to_string,
generic(
path = GenInfo,
method_name = info
)
),
trait(
context = p04::max,
type = f64,
converter = generic_info,
simple(
path = my::DetailedInfo,
method_name = info
)
)
)]
struct Person {
#[context_attribute(context(name=p01::average, skip))]
#[context_attribute(context(name=p02::max, skip))]
name: String
/// Age in years
#[context_attribute(context(name=p01::average, skip))]
#[context_attribute(context(name=p02::max, skip))]
age: usize,
/// Dept in $ in the certain banks
#[context_attribute(
context(name=p02::max, converter=punishment::with_interests)
)]
dept: BTreeMap<String, f64>,
/// Amount of money in banks. Accounts in $
bank_account: BTreeMap<String, f64>,
/// Amount of money in the wallet in $
wallet: f64,
/// Amount of money in the crypto in crypto-wallets. Transformed to $
crypto: BTreeMap<String, f64>
}
Macros documentation
See ContextMapper
for detailed info
Comparsion to similar libraries
serde
The main difference between context_mapper
and serde
is the approach.
serde
defines single, powerful way of serializing / deserializing
structures, enums etc. On the other hand context_mapper
does not enforce
any standard on the serialization. Its main purpose is to simplify generation of
the repetitive struct -> map mappings. Also, it does not support nested structures
structmap
While being inspiration for this library, structmap
is more similar
to serde, than context_mapper
. Both libraries provide way of converision
of the struct to map of strings. However structmap
allows users to convert
objects from map and then convert them to map. On the other hand it does not
allow multiple contexts (multiple maps generation)
Dependencies
~0.7–1.1MB
~21K SLoC