12 个稳定版本

1.3.1 2023 年 9 月 20 日
1.3.0 2023 年 9 月 4 日
1.2.9 2023 年 8 月 29 日
1.2.7 2023 年 3 月 11 日
0.1.1 2022 年 9 月 7 日

2083Rust 模式 中排名

Download history 10/week @ 2024-04-14 3/week @ 2024-04-21 19/week @ 2024-05-05 17/week @ 2024-05-12 44/week @ 2024-05-19 8/week @ 2024-05-26 22/week @ 2024-06-02 32/week @ 2024-06-09 3/week @ 2024-06-16 12/week @ 2024-06-23 30/week @ 2024-06-30 1/week @ 2024-07-07 1/week @ 2024-07-14 221/week @ 2024-07-28

每月 223 次下载

MIT 许可证

27KB
473 代码行

结构体转换

此包提供了一组可定制的 #[derive] 属性,用于 Rust,以帮助您简化结构体之间的转换。

它能做什么

use struct_convert::Convert;

#[derive(Convert)]
#[convert(from = "some_mod::Remote")]
#[convert(from = "C")]
#[convert(into = "B")]
struct A {
    value: i64,
}

struct B {
    value: i64,
}

struct C {
    value: i64,
}

mod some_mod {
    pub struct Remote {
        pub value: i64,
    }
}

fn main() {}

#[test]
fn test_proxy() {
    let c = C { value: 8 };
    let a: A = c.into();
    let b: B = a.into();
    debug_assert_eq!(8, b.value);

    let r = some_mod::Remote { value: 7 };
    let a2: A = r.into();
    debug_assert_eq!(7, a2.value);
}

查看 示例 了解更多!

示例

Derivative 和 struct-convert 的组合

use derivative::Derivative;
use struct_convert::Convert;
use time::OffsetDateTime;

#[derive(Derivative, Convert, Debug)]
#[derivative(Default)]
#[convert(default)]
#[convert(from = "A")]
struct SomeStruct {
    name: String,
    #[derivative(Default(value = "OffsetDateTime::now_utc()"))]
    #[convert_field(from="A", ignore)]
    at: OffsetDateTime,
}

struct A {
    name: String,
}

fn main() {
    let a = A{
        name: "A".to_string()
    };
    let ss: SomeStruct = a.into();
    println!("{:?}", ss);
    // SomeStruct { name: "A", at: 2023-03-03 6:13:32.5684174 +00:00:00 }
}

内部结构转换。

use struct_convert::Convert;

#[derive(Debug, PartialEq)]
struct BInner {
    name: String,
}

#[derive(Debug, PartialEq)]
struct B {
    bid: i64,
    inner: BInner,
}

#[derive(Debug, Convert, PartialEq)]
#[convert(into = "B")]
struct A {
    #[convert_field(rename = "bid")]
    id: i64,

    inner: AInner,
}

#[derive(Debug, Convert, PartialEq)]
#[convert(into = "BInner")]
struct AInner {
    name: String,
}

fn main() {
    let a = A {
        id: 2,
        inner: AInner {
            name: String::from("AInner"),
        },
    };
    let b: B = a.into();
    debug_assert_eq!(
        B {
            bid: 2,
            inner: BInner {
                name: String::from("AInner")
            },
        },
        b
    );
}

可选字段转换。

use struct_convert::Convert;

#[derive(Debug, PartialEq)]
struct BInner {
    name: String,
}

#[derive(Debug, PartialEq)]
struct B {
    name: String,
    name2: String,
    opt_str: Option<String>,
    opt_str2: Option<String>,
}

#[derive(Debug, Convert, PartialEq)]
#[convert(into = "B")]
struct A {
    #[convert_field(unwrap)]
    name: Option<String>,

    #[convert_field(unwrap)]
    name2: Option<String>,

    #[convert_field(option)]
    opt_str: String,

    #[convert_field(option)]
    opt_str2: Option<String>,
}

#[derive(Debug, Convert, PartialEq)]
#[convert(into = "BInner")]
struct AInner {
    name: String,
}

fn main() {
    let a = A {
        name: Some("Jack".to_string()),
        opt_str: String::from("str"),
        opt_str2: Some(String::from("Option")),
        name2: None,
    };
    let b: B = a.into();
    debug_assert_eq!(
        B {
            name: "Jack".to_string(),
            opt_str: Some(String::from("str")),
            opt_str2: Some(String::from("Option")),
            name2: "".to_string()
        },
        b
    );
}

忽略某些字段。

use struct_convert::Convert;

#[derive(Debug, PartialEq)]
struct B {
    num: String,
    name: String,
}

#[derive(Debug, Convert, PartialEq)]
#[convert(into = "B")]
struct A {
    #[convert_field(ignore)]
    id: i64,

    #[convert_field(to_string)]
    num: i64,

    #[convert_field(unwrap)]
    name: Option<String>,
}

fn main() {
    let a = A {
        id: 2,
        num: 1,
        name: Some("Jack".to_string()),
    };
    let b: B = a.into();
    debug_assert_eq!(
        B {
            num: "1".to_string(),
            name: "Jack".to_string(),
        },
        b
    );
}

从 A 转换为 B

use struct_convert::Convert;

#[derive(Debug, Convert, PartialEq)]
#[convert(from = "AInner")]
struct BInner {
    name: String,
}

#[derive(Debug, Convert, PartialEq)]
#[convert(from = "A")]
struct B {

    #[convert_field(rename = "id")]
    bid: i64,

    #[convert_field(to_string)]
    num: String,

    #[convert_field(unwrap)]
    name: String,

    inner: BInner,

    #[convert_field(wrap)]
    opt_str: Option<String>,

    opt_str2: Option<String>
}

#[derive(Debug,  PartialEq)]
struct A {
    ignore_f: i64,
    id: i64,
    num: i64,
    name: Option<String>,
    inner: AInner,
    opt_str: String,
    opt_str2: Option<String>,
}


#[derive(Debug, PartialEq)]
struct AInner {
    name: String,
}

fn main() {
    let a = A {
        id: 2,
        num: 1,
        name: Some("Jack".to_string()),
        inner: AInner {
            name: String::from("AInner"),
        },
        opt_str: String::from("str"),
        opt_str2: Some(String::from("Option")),
        ignore_f: 1,
    };
    let b: B = a.into();
    debug_assert_eq!(
        B {
            num: "1".to_string(),
            bid: 2,
            name: "Jack".to_string(),
            inner: BInner {
                name: String::from("AInner")
            },
            opt_str: Some(String::from("str")),
            opt_str2: Some(String::from("Option"))
        },
        b
    );
}

使用自定义函数转换。

use struct_convert::Convert;

#[derive(Debug, PartialEq)]
struct B {
    bid: i64,
}

#[derive(Debug, Convert, PartialEq)]
#[convert(into = "B")]
struct A {
    #[convert_field(rename = "bid", custom_fn = "str_to_i64")]
    id_str: String,
}

#[derive(Debug, Convert, PartialEq)]
#[convert(from = "B")]
struct C {
    #[convert_field(rename = "bid", custom_fn = "to_point")]
    point: Point,
}

#[derive(Debug, PartialEq)]
struct Point(i64, i64);

fn str_to_i64(a: &A) -> i64 {
    a.id_str.parse().unwrap()
}

fn to_point(b: &B) -> Point {
  Point(b.bid, b.bid)
}

fn main() {
    let a = A { id_str: "4".into() };
    let b: B = a.into();
    debug_assert_eq!(B { bid: 4 }, b);
    let c: C = b.into();
    debug_assert_eq!(C { point: Point(4, 4) }, c);

}

更多示例请查看 此处

欢迎提交 PR。

依赖项

~3MB
~67K SLoC