use std::ops::Range;
use xot::{Error, Node, Xot};
use crate::apply::apply_diff;
use crate::comparison::Comparison;
use crate::vtree::Status;
use crate::Edit;
pub struct NaturalXmlDiff<'a> {
xot: Xot<'a>,
comparison: Comparison,
}
impl<'a> NaturalXmlDiff<'a> {
pub fn new(xml_a: &str, xml_b: &str) -> Result<Self, Error> {
let mut xot = Xot::new();
let comparison = Comparison::from_xml(&mut xot, xml_a, xml_b)?;
Ok(Self { xot, comparison })
}
pub fn diff(&mut self) -> String {
let node = self.comparison.diff(&mut self.xot);
self.xot.serialize_to_string(node)
}
pub fn verify(&mut self) -> Result<(), String> {
self.comparison.verify(&mut self.xot)
}
pub fn edits(&mut self) -> Vec<Edit> {
self.comparison.edits(&mut self.xot)
}
pub fn partition(&mut self) -> Vec<(Range<usize>, Range<usize>)> {
self.comparison.partition()
}
pub fn diff_status(
&mut self,
) -> (
impl Iterator<Item = (Node, Status)> + '_,
impl Iterator<Item = (Node, Status)> + '_,
) {
self.comparison.diff_status(&self.xot);
let status_a = self
.comparison
.vtree_a
.nodes
.iter()
.map(|vnode| (vnode.node, vnode.status));
let status_b = self
.comparison
.vtree_b
.nodes
.iter()
.map(|vnode| (vnode.node, vnode.status));
(status_a, status_b)
}
pub fn serialize(&mut self, node: Node) -> String {
self.xot.serialize_node_to_string(node)
}
pub fn xot(&self) -> &Xot {
&self.xot
}
}
pub fn diff(xml_a: &str, xml_b: &str) -> Result<String, Error> {
let mut nxd = NaturalXmlDiff::new(xml_a, xml_b)?;
Ok(nxd.diff())
}
pub fn apply(diff_xml: &str) -> Result<String, Error> {
let mut xot = Xot::new();
let doc = xot.parse(diff_xml)?;
apply_diff(&mut xot, doc);
Ok(xot.serialize_to_string(doc))
}