use crate::basic::persistent_btree::{NodeId, PersistentBTree};
use std::cmp::Ordering;
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum DiffEntry {
Added { key: Vec<u8>, value: Vec<u8> },
Removed { key: Vec<u8>, value: Vec<u8> },
Modified {
key: Vec<u8>,
old_value: Vec<u8>,
new_value: Vec<u8>,
},
}
pub fn diff_roots(
tree: &PersistentBTree,
old_root: NodeId,
new_root: NodeId,
) -> Vec<DiffEntry> {
if old_root == new_root {
return Vec::new();
}
let mut iter_old = tree.iter(old_root).peekable();
let mut iter_new = tree.iter(new_root).peekable();
let mut result = Vec::new();
loop {
match (iter_old.peek(), iter_new.peek()) {
(None, None) => break,
(Some(_), None) => {
let (k, v) = iter_old.next().unwrap();
result.push(DiffEntry::Removed { key: k, value: v });
}
(None, Some(_)) => {
let (k, v) = iter_new.next().unwrap();
result.push(DiffEntry::Added { key: k, value: v });
}
(Some((ok, _)), Some((nk, _))) => match ok.cmp(nk) {
Ordering::Less => {
let (k, v) = iter_old.next().unwrap();
result.push(DiffEntry::Removed { key: k, value: v });
}
Ordering::Greater => {
let (k, v) = iter_new.next().unwrap();
result.push(DiffEntry::Added { key: k, value: v });
}
Ordering::Equal => {
let (k, ov) = iter_old.next().unwrap();
let (_, nv) = iter_new.next().unwrap();
if ov != nv {
result.push(DiffEntry::Modified {
key: k,
old_value: ov,
new_value: nv,
});
}
}
},
}
}
result
}