use ahash::HashMap;
use xot::{Error, Node, Xot};
use crate::vtree::{Signatures, Status, Vtree};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) struct EqualPair(pub(crate) usize, pub(crate) usize);
type TreeSignatureIdToIndices = HashMap<u32, Vec<usize>>;
pub(crate) struct Comparison {
pub(crate) doc_a: Node,
pub(crate) doc_b: Node,
pub(crate) vtree_a: Vtree,
pub(crate) vtree_b: Vtree,
pub(crate) vtree_b_index: TreeSignatureIdToIndices,
}
impl Comparison {
pub(crate) fn new(xot: &Xot, doc_a: Node, doc_b: Node) -> Self {
let mut node_signatures = Signatures::new();
let mut tree_signatures = Signatures::new();
let vtree_a = Vtree::new(xot, doc_a, &mut node_signatures, &mut tree_signatures);
let vtree_b = Vtree::new(xot, doc_b, &mut node_signatures, &mut tree_signatures);
let mut vtree_b_index: TreeSignatureIdToIndices = HashMap::default();
for (index, vnode) in vtree_b.nodes.iter().enumerate() {
vtree_b_index
.entry(vnode.tree_signature_id)
.or_default()
.push(index)
}
Self {
doc_a,
doc_b,
vtree_a,
vtree_b,
vtree_b_index,
}
}
pub(crate) fn from_xml(xot: &mut Xot, xml_a: &str, xml_b: &str) -> Result<Self, Error> {
let doc_a = xot.parse(xml_a)?;
let doc_b = xot.parse(xml_b)?;
Ok(Self::new(xot, doc_a, doc_b))
}
pub(crate) fn update_status(&mut self, pairs: &[EqualPair], f: impl Fn(u32) -> Status) {
for pair in pairs {
let EqualPair(id_a, id_b) = *pair;
let vnode_a = &mut self.vtree_a.nodes[id_a];
vnode_a.status = f(id_b as u32);
let vnode_b = &mut self.vtree_b.nodes[id_b];
vnode_b.status = f(id_a as u32);
}
}
#[cfg(test)]
pub(crate) fn vtrees(&self) -> (&Vtree, &Vtree) {
(&self.vtree_a, &self.vtree_b)
}
pub(crate) fn get_node_a(&self, id: usize) -> Node {
self.vtree_a.nodes[id].node
}
pub(crate) fn get_node_b(&self, id: usize) -> Node {
self.vtree_b.nodes[id].node
}
}