#patch #struct #struct-fields #no-alloc

无std rust-patch

使用其他结构体修补结构体

4个版本

0.1.3 2023年2月27日
0.1.2 2023年2月23日
0.1.1 2023年2月23日
0.1.0 2023年2月22日

422无标准库

Download history 536/week @ 2024-04-20 261/week @ 2024-04-27 362/week @ 2024-05-04 428/week @ 2024-05-11 234/week @ 2024-05-18 209/week @ 2024-05-25 329/week @ 2024-06-01 522/week @ 2024-06-08 541/week @ 2024-06-15 440/week @ 2024-06-22 136/week @ 2024-06-29 177/week @ 2024-07-06 184/week @ 2024-07-13 163/week @ 2024-07-20 216/week @ 2024-07-27 224/week @ 2024-08-03

每月 832 次下载
2 个crates中使用了(通过 pagefind

MIT/Apache

10KB

rust-patch

使用其他结构体修补结构体

Build status Crates.io Documentation

rust-patch 允许您在实现Rust结构体的部分更新时避免样板代码。
只需定义一个包含您字段子集的修补结构体,派生 Patch 特性,并使用 #[patch] 属性指定原始结构体。
修补结构体的字段可以是与原始结构体相同的类型 T,或者是 Option<T>
在后一种情况下,如果修补中对应的字段是 None,则将被修补的字段将保持不变。

此crate与 no_std 兼容。

容器属性

#[修补 = "..."]

设置要修补的目标结构体

use rust_patch::Patch;
struct Item { data: u32 }

#[derive(Patch)]
#[patch = "Item"]
struct ItemPatch { data: Option<u32> }

字段属性

默认情况下,任何类型为 Option<T> 的修补字段都将按原样应用

if let Some(val) = patch.field {
    target.field = val;
} 

可以通过以下字段属性更改此行为。

#[修补(as_option)]

as_option 属性允许修补具有以下逻辑的结构体,其中字段本身已经是 Option<T>

if patch.field.is_some() {
    target.field = patch.field;
}

如果将此属性应用于没有 is_some() 方法的类型,则会引发错误。

#[修补(direct)]

direct 属性使得字段被像任何其他 T 一样处理,这意味着它将按以下方式应用

target.field = patch.field;

如果将此属性应用于不是 Option<T> 的类型,则为空操作。

示例

use rust_patch::Patch;
use serde::Deserialize;

#[derive(PartialEq, Debug)]
struct User {
    id: String,
    name: String,
    email: String,
}

#[derive(Deserialize, Patch)]
#[patch = "User"]
struct UserPatch {
    name: Option<String>,
    email: Option<String>,
}

let user = User {
    id: "6bf25b70-bffa-49e0-905b-2d2e608e3abd".to_string(),
    name: "Max Mustermann".to_string(),
    email: "[email protected]".to_string(),
};

let raw_patch = r#"{
    "id": "some invalid id",
    "email": "[email protected]"
}"#;

let patch: UserPatch = serde_json::from_str(raw_patch).unwrap();
let patched_user = patch.apply(user);

// Since `id` is not part of our `UserPatch` struct it stays unchanged
assert_eq! {
    patched_user,
    User {
        id: "6bf25b70-bffa-49e0-905b-2d2e608e3abd".to_string(),
        name: "Max Mustermann".to_string(),
        email: "[email protected]".to_string()
    }
};

依赖

~1.5MB
~36K SLoC