diff --git a/src/main.rs b/src/main.rs index 059344a..6788dc0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1092,4 +1092,59 @@ impl TextLineFontKind { } } +#[derive(Debug)] +struct ElementBodyBuilder<'a> { + containing_element: &'a mut xml_tree::Element, + stack: Vec, +} + +impl<'a> ElementBodyBuilder<'a> { + fn new(containing_element: &'a mut xml_tree::Element) -> Self { + Self { + containing_element, + stack: Vec::with_capacity(5), + } + } + fn shrink_stack(&mut self, new_len: usize) { + while new_len < self.stack.len() { + let Some(element) = self.stack.pop() else { + unreachable!(); + }; + self.insert_point().children.push(element); + } + } + fn set_tag_stack<'b>(&mut self, tag_stack: impl IntoIterator) { + let mut new_len = 0; + for (i, tag) in tag_stack.into_iter().enumerate() { + new_len = i + 1; + if i >= self.stack.len() { + self.stack.push(xml_tree::Element::new(tag.into(), [])); + } else if self.stack[i].tag.normal() != Some(tag) { + self.shrink_stack(new_len); + } + } + self.shrink_stack(new_len); + } + fn write_text(&mut self, text: impl Borrow) { + let text = text.borrow(); + let insert_point = self.insert_point(); + if let Some(child) = insert_point.children.last_mut() { + child.tail += text; + } else { + insert_point.text += text; + } + } + fn insert_point(&mut self) -> &mut xml_tree::Element { + self.stack.last_mut().unwrap_or(self.containing_element) + } + fn scope(&mut self, f: impl FnOnce(&mut Self) -> R) -> R { + let retval = f(self); + self.flush(); + retval + } + fn flush(&mut self) { + self.set_tag_stack([]); + } +} + fn main() {} diff --git a/src/xml_tree.rs b/src/xml_tree.rs index 4a0ed52..1fce103 100644 --- a/src/xml_tree.rs +++ b/src/xml_tree.rs @@ -157,6 +157,15 @@ impl fmt::Display for Element { } impl Element { + pub(crate) fn new(tag: String, attrib: impl IntoIterator) -> Self { + Self { + tag: ElementTag::Normal(tag), + attrib: Vec::from_iter(attrib), + text: String::new(), + children: Vec::new(), + tail: String::new(), + } + } /// equivalent to python `"".join(self.itertext())` pub(crate) fn inner_text(&self) -> String { let mut retval = String::new(); @@ -186,13 +195,7 @@ impl Element { tag: String, attrib: impl IntoIterator, ) -> &mut Self { - self.children.push(Self { - tag: ElementTag::Normal(tag), - attrib: Vec::from_iter(attrib), - text: String::new(), - children: Vec::new(), - tail: String::new(), - }); + self.children.push(Self::new(tag, attrib)); self.children.last_mut().expect("just pushed") } }