14个版本 (8个破坏性版本)
0.10.0 | 2021年5月17日 |
---|---|
0.9.1 | 2020年1月1日 |
0.9.0 | 2019年12月31日 |
0.4.0 | 2019年11月26日 |
#84 in #difference
每月下载量 158次
用于 diffus
16KB
302 行
Diffus
寻找任何数据结构两个实例之间的差异。
Diffus 在行动
use diffus_derive::Diffus;
use diffus::{edit, Diffable};
#[derive(Diffus)]
struct Point {
x: i32,
y: i32,
}
fn main() {
let left_point = Point { x: 1, y: 2 };
let right_point = Point { x: 1, y: 3 };
let diff = left_point.diff(&right_point);
match diff {
edit::Edit::Copy => println!("point: no difference"),
edit::Edit::Change(EditedPoint { x, y }) => {
match x {
edit::Edit::Copy => println!("x: no difference"),
edit::Edit::Change((left_x, right_x)) => println!("x: {} => {}", left_x, right_x),
}
match y {
edit::Edit::Copy => println!("y: no difference"),
edit::Edit::Change((left_y, right_y)) => println!("y: {} => {}", left_y, right_y),
}
}
}
}
Diffus 在映射中
通过其键来完成映射之间的差异。元素的标识来自其关联的键,否则它与具有 Same
的集合以相同的方式工作。
映射的可能编辑为 Copy
、Insert
、Remove
、Change
。
use diffus::{edit, Diffable};
fn main() {
let unity: std::collections::HashMap<_, _> =
[(1, 1), (2, 2), (3, 3)].iter().cloned().collect();
let not_unity: std::collections::HashMap<_, _> =
[(1, 1), (2, 3), (4, 4)].iter().cloned().collect();
if let edit::Edit::Change(diff) = unity.diff(¬_unity) {
assert!(diff[&1].is_copy());
assert_eq!(diff[&2].change().unwrap(), &(&2, &3));
assert!(diff[&3].is_remove());
assert_eq!(diff[&4].insert().unwrap(), &4);
} else {
unreachable!()
}
}
Diffus 在集合中
通过最长公共子序列 (LCS) 算法来完成集合之间的差异,并支持值已更改但保持其 Same
"身份" 的对象。
字符串被视为集合。
集合的可能编辑为 Copy
、Insert
、Remove
、Change
。
use diffus_derive::Diffus;
use diffus::{edit::{self, collection}, Same, Diffable};
#[derive(Diffus, Debug)]
struct Identified {
id: u32,
value: u32,
}
impl Same for Identified {
fn same(&self, other: &Self) -> bool {
self.id == other.id
}
}
fn main() {
let left = vec![
Identified { id: 1, value: 0 },
Identified { id: 2, value: 0 },
Identified { id: 3, value: 0 },
Identified { id: 4, value: 0 },
Identified { id: 5, value: 0 },
Identified { id: 6, value: 0 },
Identified { id: 7, value: 0 },
];
let right = vec![
Identified { id: 1, value: 0 },
Identified { id: 2, value: 1 },
Identified { id: 4, value: 0 },
Identified { id: 3, value: 0 },
Identified { id: 5, value: 0 },
Identified { id: 6, value: 0 },
];
let diff = left.diff(&right);
match diff {
edit::Edit::Copy => println!("no difference"),
edit::Edit::Change(diff) => {
diff.into_iter().map(|edit| {
match edit {
collection::Edit::Copy(elem) => println!("copy: {:?}", elem),
collection::Edit::Insert(elem) => println!("insert: {:?}", elem),
collection::Edit::Remove(elem) => println!("remove: {:?}", elem),
collection::Edit::Change(EditedIdentified { id, value}) => {
println!("changed:");
match id {
edit::Edit::Copy => println!(" copy: id"),
edit::Edit::Change((left_id, right_id)) => println!(" id: {} => {}", left_id, right_id),
}
match value {
edit::Edit::Copy => println!(" copy: value"),
edit::Edit::Change((left_value, right_value)) => println!(" value: {} => {}", left_value, right_value),
}
}
};
}).collect::<Vec<_>>();
},
};
}
Diffus 在枚举中
两个枚举之间的差异按预期工作,它将变体更改与关联变体字段更改分开。
枚举的可能编辑为 Copy
、VariantChanged
、AssociatedChanged
。
use diffus_derive::Diffus;
use diffus::{edit, Diffable};
#[derive(Diffus, Debug, PartialEq)]
enum Test {
A,
B(String),
Bd(String, u32),
C { x: u32 },
Cd { x: u32, y: String },
}
fn main() {
let left = Test::Cd {
x: 42,
y: "Bilbo Baggins".to_owned(),
};
let right = Test::Cd {
x: 42,
y: "Frodo Baggins".to_owned(),
};
if let edit::Edit::Change(edit::enm::Edit::AssociatedChanged(
EditedTest::Cd { x, y },
)) = left.diff(&right)
{
assert!(x.is_copy());
assert!(y.is_change());
} else {
unreachable!()
}
let left = Test::Cd {
x: 42,
y: "Bilbo Baggins".to_owned(),
};
let right = Test::B("Frodo Baggins".to_owned());
if let edit::Edit::Change(edit::enm::Edit::VariantChanged(l, r)) =
left.diff(&right)
{
assert_eq!(&left, l);
assert_eq!(&right, r);
} else {
unreachable!()
}
}
使用 diffus 定制差异
差异可以很容易地专门化以适应您的需求。
use diffus::{edit, Diffable};
struct Secret(String);
impl<'a> Diffable<'a> for Secret {
type Diff = ();
fn diff(&'a self, other: &'a Self) -> edit::Edit<Self::Diff> {
if self.0 == other.0 {
edit::Edit::Copy
} else {
edit::Edit::Change(())
}
}
}
fn main() {
assert_eq!(
Secret("Something".to_owned()).diff(&Secret("Else".to_owned()))
.change().unwrap(),
&()
);
}
依赖项
~1.5MB
~35K SLoC