#difference #struct #diff #delta-compression #instance #partial #zero-dependency

structdiff

用于生成和应用结构实例之间部分差异的无依赖crate

19个版本

0.7.1 2024年4月25日
0.6.3 2024年3月16日
0.5.9 2023年10月30日
0.5.7 2023年5月11日
0.4.1 2022年11月13日

#84 in 压缩

Download history 65/week @ 2024-04-26 1/week @ 2024-05-03 1/week @ 2024-05-24 4/week @ 2024-05-31 1/week @ 2024-06-07 1/week @ 2024-06-28 18/week @ 2024-07-05 103/week @ 2024-07-26 9/week @ 2024-08-02

每月112次下载

Apache-2.0 OR MIT

155KB
4K SLoC

structdiff

一个轻量级、无依赖的结构差异库,允许收集和应用更改的字段。在结构上派生Difference,然后使用StructDiff特质来创建和应用差异。支持使用serdenanoserde对生成的差异类型进行可选序列化,以便于使用。

Crates.io

示例

use structdiff::{Difference, StructDiff};

#[derive(Debug, PartialEq, Clone, Difference)]
struct Example {
    field1: f64,
    #[difference(skip)]
    field2: Vec<i32>,
    #[difference(collection_strategy="unordered_array_like")]
    field3: BTreeSet<usize>,
}

let first = Example {
    field1: 0.0,
    field2: vec![],
    field3: vec![1, 2, 3].into_iter().collect(),
};

let second = Example {
    field1: 3.14,
    field2: vec![1],
    field3: vec![2, 3, 4].into_iter().collect(),
};

let diffs = first.diff(&second);
// diffs is now a Vec of differences between the two instances, 
// with length equal to number of changed/unskipped fields
assert_eq!(diffs.len(), 2);

let diffed = first.apply(diffs);
// diffed is now equal to second, except for skipped field
assert_eq!(diffed.field1, second.field1);
assert_eq!(&diffed.field3, &second.field3);
assert_ne!(diffed, second);

更多示例请参阅集成测试

派生宏属性

  • #[difference(skip)] - 在创建差异时不考虑此字段
  • #[difference(recurse)] - 在创建差异时为该字段生成StructDiff
  • #[difference(collection_strategy= {})]
    • "ordered_array_like" - 为实现PartialEq的有序、类似数组的项集合生成最小更改集。(使用levenshtein差异)
    • "unordered_array_like" - 为实现Hash + Eq的无序、类似数组的项集合生成最小更改集。
    • "unordered_map_like" - 为键实现Hash + Eq的无序、类似映射的集合生成最小更改集。
  • #[difference(map_equality = {})] - 与unordered_map_like一起使用
    • "key_only" - 仅替换键值对中键已更改的项
    • "key_and_value" - 如果键或值中任一更改,则替换键值对
  • #[difference(setters)] - 为结构体中所有字段生成setter(用于结构体)
    • 示例:对于上述使用的 Example 结构体的 field1 字段,将生成一个具有以下签名的函数:set_field1_with_diff(&mut self, value: Option<usize>) -> Option<<Self as StructDiff>::Diff>。当结构体有许多字段且仅更改单个字段时很有用,因为它节省了比较其他所有字段的时间。
  • #[difference(setter)] - 为此结构体字段生成setter(用于字段)
  • #[difference(setter_name = {})] - 在为该字段生成setter时使用此名称代替默认值(用于字段)

可选功能

  • [nanoserde, serde] - 序列化从 Difference 派生的关联类型。允许diff轻松通过网络发送。
  • debug_diffs - 在生成的diff类型上派生 Debug
  • generated_setters - 启用为结构体字段生成setter。这些setter在赋值更改字段值时自动返回一个diff。
  • rustc_hash - 使用来自 rustc-hash 包的(非加密)哈希实现,而不是默认的哈希器。这会以依赖项为代价为集合提供更快的diff生成。

开发状态

此库目前正在我的项目中积极使用,尽管目前大多数功能都已实现。接受有关更多测试或功能的PR。

依赖关系

~210KB