6 releases
0.1.6 | Dec 6, 2023 |
---|---|
0.1.5 | Dec 5, 2023 |
0.1.3 | Nov 29, 2023 |
#327 in Procedural macros
47 downloads per month
30KB
696 lines
just-convert
Easy conversion of structures
Example
#[derive(JustConvert, Default)]
#[convert(from_into(other::Mouse))]
#[convert(from_into(Cat, default))]
struct Dog {
#[convert(unwrap(from(Cat)))]
name: String,
#[convert(skip(from(other::Mouse)))]
#[convert(map(from(Cat, ". as i64"), into(Cat, ". as u64")))]
age: i64,
// inner of Option must be autoconvert
#[convert(skip(from_into(other::Mouse)))]
#[convert(map = ".map(Into::into)")]
error: Option<DogError>,
}
#[derive(JustConvert, Default)]
struct Cat {
name: Option<String>,
age: u64,
// inner of Option must be autoconvert
error: Option<CatError>,
}
mod other {
pub struct Mouse {
pub name: String,
}
}
Convert both sides at once
Specify the value for from_into
as #[convert(from_into(Struct))]
, instead of specifying from
and into
separately
#[derive(JustConvert)]
#[convert(from_into(some::B))]
struct A {
// ...
}
Rename field
#[derive(JustConvert)]
#[convert(from_into(some::B))]
struct A {
#[convert(rename = user_id)]
id: String,
}
struct B {
user_id: String,
}
Execute an arbitrary expression for the conversion
Use the map
attribute to specify an arbitrary expression
To access the current field, use the dot character, for e.g., ".get_value()".
To access the current structure, use the this
construct, e.g. "this.field.get_value()"
#[derive(JustConvert)]
#[convert(from(B))]
struct A {
// call any method of this field
#[convert(map = ".to_hex_string()")]
id: Uuid,
// casting (or "this.age as i64")
#[convert(map = ". as i64")]
age: i64,
// call any expression
#[convert(map = "format!(\"id: {}, age: {}\", this.id, this.age)")]
message: String,
}
struct B {
id: String,
age: u64,
}
Auto convert types inside Option or Vec (and Option<Vec> and Vec<Option>)
#[derive(JustConvert)]
#[convert(from(B))]
struct A {
value: Option<ValueA>,
items: Vec<ValueA>,
}
struct B {
value: Option<ValueB>,
items: Vec<ValueB>,
}
Ignore some fields
Use the skip
attribute to ignore convert
#[derive(JustConvert)]
#[convert(from(B))]
struct A {
id: String,
#[convert(skip)]
age: i64,
}
struct B {
id: String
}
Declare multiple conversions
Use the #[convert(...)]
attribute as many times as needed
#[derive(JustConvert)]
#[convert(from(B))]
#[convert(from_into(C))]
struct A {
id: String,
#[convert(skip)]
age: i64,
}
struct B {
id: String,
}
struct C {
id: String,
}
Specialize the value of attributes for each transformation
Optionally, you can specify for which transformation the value
specified in the attribute applies. For example, to rename a field
only for a from' conversion:
#[convert(rename(from = new_name))]or for a specific
#[convert(rename(from(StructName, new_name)))]`
Rules by which values can be specialized:
- Boolean values
#[convert(wrap)]
:#[convert(wrap(from))]
and#[convert(wrap(from(StructName)))]
- Other (with assignment)
#[convert(map = "some_expr")]
:#[convert(map(from = "some_expr"))]
and#[convert(map(from(StructName, "some_expr")))]
#[derive(JustConvert)]
#[convert(from(B))]
#[convert(from_into(C))]
struct A {
#[convert(rename(from_into(C, c_id)))]
#[convert(rename(from = user_id))] // or #[convert(rename(from(B, user_id)))]
id: String,
#[convert(skip)]
age: i64,
}
struct B {
user_id: String,
}
struct C {
c_id: String,
}
Inspiration
Thanks to the struct-convert and derive-from-ext libraries
Dependencies
~265–720KB
~17K SLoC