#![deny(missing_docs)]
use serde_json::Value;
#[derive(Debug, Clone)]
pub struct Step {
pub kind: String,
pub key: String,
pub payload: Value,
}
#[derive(Debug, Clone, PartialEq)]
#[allow(missing_docs)]
pub enum Change {
Added { index: usize, kind: String, key: String },
Removed { index: usize, kind: String, key: String },
Changed {
index: usize,
kind: String,
key: String,
baseline: Value,
new: Value,
},
}
pub fn diff(base: &[Step], new: &[Step]) -> Vec<Change> {
let mut out = Vec::new();
let max = base.len().max(new.len());
for i in 0..max {
match (base.get(i), new.get(i)) {
(Some(b), Some(n)) => {
if b.kind != n.kind || b.key != n.key {
out.push(Change::Removed {
index: i,
kind: b.kind.clone(),
key: b.key.clone(),
});
out.push(Change::Added {
index: i,
kind: n.kind.clone(),
key: n.key.clone(),
});
} else if b.payload != n.payload {
out.push(Change::Changed {
index: i,
kind: b.kind.clone(),
key: b.key.clone(),
baseline: b.payload.clone(),
new: n.payload.clone(),
});
}
}
(Some(b), None) => out.push(Change::Removed {
index: i,
kind: b.kind.clone(),
key: b.key.clone(),
}),
(None, Some(n)) => out.push(Change::Added {
index: i,
kind: n.kind.clone(),
key: n.key.clone(),
}),
(None, None) => unreachable!(),
}
}
out
}