#serialization #difference #diff #structs #field #enums #apply

serde-diff

一个用于序列化相同类型两个struct之间的差异并将这些差异应用到其他struct上的小助手

9个版本

0.4.1 2021年1月12日
0.4.0 2021年1月2日
0.3.1 2020年8月11日
0.3.0 2020年3月7日
0.1.3 2019年11月9日

#322 in 编码

Download history 124/week @ 2024-03-13 92/week @ 2024-03-20 88/week @ 2024-03-27 108/week @ 2024-04-03 104/week @ 2024-04-10 79/week @ 2024-04-17 74/week @ 2024-04-24 57/week @ 2024-05-01 138/week @ 2024-05-08 91/week @ 2024-05-15 59/week @ 2024-05-22 119/week @ 2024-05-29 411/week @ 2024-06-05 313/week @ 2024-06-12 122/week @ 2024-06-19 157/week @ 2024-06-26

每月1,026次下载
2 个crate中使用 (通过 跟踪)

Apache-2.0 OR MIT

77KB
1.5K SLoC

serde-diff

一个可以

  1. 序列化相同类型两个值之间差异的字段的小助手
  2. 将之前序列化的字段差异应用到相同类型的其他值上。

SerdeDiff trait 实现将字段路径递归序列化,大大减少了在struct/enum的很小部分发生变化时需要序列化的数据量。

Build Status Crates.io Docs.rs

使用方法

在struct或enum上

#[derive(SerdeDiff, Serialize, Deserialize)]

序列化并应用各种格式下的差异

rmp_serde (MessagePack - 非常小的消息)

let msgpack_data = rmp_serde::to_vec_named(&Diff::serializable(&old, &new))?;
let mut deserializer = rmp_serde::Deserializer::new(msgpack_data.as_slice());
Apply::apply(&mut deserializer, &mut target)?;

bincode (非常快的序列化和反序列化)

let bincode_data = bincode::serialize(&Diff::serializable(&old, &new))?;
bincode::config().deserialize_seed(Apply::deserializable(&mut target), &bincode_data)?;

serde_json

        let json_data = serde_json::to_string(&Diff::serializable(&old, &new))?;
        let mut deserializer = serde_json::Deserializer::from_str(&json_data);
        Apply::apply(&mut deserializer, &mut target)?;

内置类型支持

  • 原始类型
  • std::time::{Duration, SystemTime}
  • std中的IP地址
  • Vec
  • HashMap (感谢 @milkey-mouse)
  • BTreeMap (感谢 @milkey-mouse)
  • 固定大小的数组 (感谢 @Boscop)
  • 元组 (感谢 @Boscop)

简单示例

Cargo.toml

[dependencies]
serde-diff = "0.3"
serde = "1"
serde_json = "1" # all serde formats are supported, serde_json is shown in this example

main.rs

use serde_diff::{Apply, Diff, SerdeDiff};
use serde::{Serialize, Deserialize};
#[derive(SerdeDiff, Serialize, Deserialize, PartialEq, Debug)]
struct TestStruct {
    a: u32,
    b: f64,
}

fn main() {
    let old = TestStruct {
        a: 5,
        b: 2.,
    };
    let new = TestStruct {
        a: 8, // Differs from old.a, will be serialized
        b: 2.,
    };
    let mut target = TestStruct {
        a: 0,
        b: 4.,
    };
    let json_data = serde_json::to_string(&Diff::serializable(&old, &new)).unwrap();
    let mut deserializer = serde_json::Deserializer::from_str(&json_data);
    Apply::apply(&mut deserializer, &mut target).unwrap();


    let result = TestStruct {
        a: 8,
        b: 4.,
    };
    assert_eq!(result, target);
}

派生宏属性

不透明结构体

#[derive(SerdeDiff, Serialize, Deserialize, PartialEq)]
#[serde_diff(opaque)] // opaque structs are serialized as a unit and fields do not need to implement SerdeDiff
struct DoesNotRecurse {
    value: ExternalType, 
}

不透明字段

#[derive(SerdeDiff, Serialize, Deserialize, PartialEq)]
struct WrapperStruct {
    #[serde_diff(opaque)]
    value: ExternalType, // opaque fields only need to implement Serialize + Deserialize + PartialEq,
}

跳过字段

#[derive(SerdeDiff, Serialize, Deserialize, PartialEq)]
struct WrapperStruct {
    #[serde_diff(skip)]
    value: ExternalType,
}

泛型

#[derive(SerdeDiff, Serialize, Deserialize, PartialEq, Debug)]
struct GenericStruct<T>
where
    T: SerdeDiff,
{
    a: T,
}

枚举

#[derive(SerdeDiff, Serialize, Deserialize, PartialEq, Debug)]
enum TestEnum {
    Structish { x: u32, y: u32 },
    Enumish(i32, i32, i32),
    Unitish,
}

贡献

所有贡献都假定在MIT/Apache-2下双许可。

许可

在MIT许可和Apache许可(版本2.0)的条款下分发。

LICENSE-APACHELICENSE-MIT.

依赖

~0.7–1.3MB
~30K SLoC