use xot::Xot;
use crate::comparison::Comparison;
use crate::partition::equal_pairs;
use crate::vtree::{Status, Vnode, Vtree};
impl Comparison {
pub(crate) fn diff_status(&mut self, xot: &Xot) {
let overlaps = self.partition();
let mut equal_pairs = equal_pairs(&overlaps);
self.update_status(&equal_pairs, Status::Equal);
let update_pairs = self.find_updates(xot, &overlaps);
self.update_status(&update_pairs, Status::Update);
equal_pairs.extend(update_pairs);
self.propagate(xot, &equal_pairs);
self.make_stray_different();
}
fn make_stray_different(&mut self) {
make_stray_different(&mut self.vtree_a, &mut self.vtree_b);
make_stray_different(&mut self.vtree_b, &mut self.vtree_a);
}
}
fn make_stray_different(vtree: &mut Vtree, other_vtree: &mut Vtree) {
let mut to_update = Vec::new();
for (index, vnode) in vtree.nodes.iter().enumerate() {
if vnode.status != Status::Different {
if has_different_ancestor(vnode, vtree) {
to_update.push(index);
match vnode.status {
Status::Equal(id) | Status::Update(id) => {
other_vtree.nodes[id as usize].status = Status::Different;
}
_ => {}
}
}
}
}
for index in to_update {
vtree.nodes[index].status = Status::Different;
}
}
fn has_different_ancestor(vnode: &Vnode, vtree: &Vtree) -> bool {
let mut parent_id = vnode.parent_id;
while let Some(current_parent_id) = parent_id {
if vtree.nodes[current_parent_id].status == Status::Different {
return true;
}
parent_id = vtree.nodes[current_parent_id].parent_id;
}
false
}
#[cfg(test)]
mod test {
use super::*;
use xot::Xot;
#[test]
fn test_diff_status_simple() {
let mut xot = Xot::new();
let doc_a = xot
.parse("<container><a/><b/><x/><c/><d/></container>")
.unwrap();
let doc_b = xot
.parse("<container><x/><a/><b/><c/><d/></container>")
.unwrap();
let mut comparison = Comparison::new(&xot, doc_a, doc_b);
comparison.diff_status(&xot);
assert_eq!(comparison.vtree_a.nodes[1].status, Status::Equal(1));
assert_eq!(comparison.vtree_a.nodes[2].status, Status::Equal(3));
assert_eq!(comparison.vtree_a.nodes[3].status, Status::Equal(4));
assert_eq!(comparison.vtree_a.nodes[5].status, Status::Equal(5));
assert_eq!(comparison.vtree_a.nodes[6].status, Status::Equal(6));
}
}