#struct #macro #another #mapping #struct-fields #data-transformation #convert

struct_morph

将一个结构体转换为另一个结构体的宏

2个不稳定版本

0.6.0 2024年3月2日
0.5.0 2024年3月1日
0.4.0 2024年3月1日
0.3.0 2024年3月1日
0.1.0 2024年3月1日

#415 in 进程宏

MIT 许可证

9KB
76

Struct Morph Rust 版本

将一个结构体转换为另一个结构体的宏。

安装

cargo add struct_morph

或手动

struct_morph = "0.6"

使用方法

我偶尔会遇到这样的用例,即我有两个结构体表示非常相似的数据。它们共享大多数字段,有时甚至可以是其中一个的子集。比如说,我们有一个从数据库中来的结构体 ProductRow,另一个结构体 ProductInfo 将作为API的JSON发送。

struct ProductRow {
    id: i32,
    name: String,
    description: String,
    available_count: i32,
    base_price: i32,
    discount: i32,
    created_at: DateTime,
    updated_at: DateTime,
}

struct ProductInfo {
    id: i32,
    name: String,
    description: String,
    is_available: bool,
    price: i32,
}

现在,对于这个小案例,当我们需要将ProductRows转换为ProductInfos时,我们可以手动完成,但对于更大的结构体来说,这变得相当机械。

使用这个库,您可以编写以下内容

use struct_morph::{morph, morph_field};

#[morph(ProductRow)]
struct ProductInfo {
    id: i32,
    #[morph_field(select = name)]
    title: String,
    description: String,
    #[morph_field(transform = "is_available")]
    is_available: bool,
    #[morph_field(transform = "net_price")]
    price: i32,
}

fn is_available(value: &ProductRow) -> bool {
    value.available_count > 0
}

fn net_price(value: &ProductRow) -> i32 {
    value.base_price - value.discount
}

然后您可以从一个产品行简单地生成一个产品信息

let product_row: ProductRow = ProductRow {
    id: 10,
    name: "The Rust Programming Language".to_string(),
    description: "The official book on the Rust programming language".to_string(),
    available_count: 10,
    base_price: 50,
    discount: 10,
    created_at: DateTime::now(),
    updated_at: DateTime::now(),
};

let product_info: ProductInfo = ProductInfo::from(product_row);

这将复制具有相同名称(和类型)的字段的值,对于其余部分,可以提供自定义转换函数。它通过为源和目标结构体实现一个 From 特性来完成。

有两种类型字段修饰符

  • 转换
#[morph_field(transform = "transform_func")]

这接受一个转换函数,该函数接受 &SourceStruct 作为参数并返回正确的类型

  • 选择
#[morph_field(select = source_field)]

这接受一个源字段来替换字段的值

依赖项

~265–710KB
~17K SLoC