parco_xml/dexml/
tag_end.rs

1use std::borrow::Cow;
2
3use crate::{
4    DeXmlError,
5    de::Reader,
6    dexml::{
7        lex::{CloseAngle, Slash},
8        parse::Action,
9    },
10};
11
12/// the ending tag of an element i.e "\>" in "\<Element\>"
13pub enum TagEnd {
14    /// A self closing tag ending with \/\>. No children
15    SelfClosing,
16    /// A normal closing tag \>. Potential children
17    Normal,
18}
19
20impl<'a> Reader<'a> {
21    /// parse the ending of a tag, if there are attributes it will consume them and then the end of the element
22    pub fn tag_end(&mut self) -> Result<TagEnd, DeXmlError> {
23        loop {
24            if self.lexer.peek('/') {
25                self.parse::<Slash>(Action::TagEnd)?;
26                self.parse::<CloseAngle>(Action::TagEnd)?;
27                return Ok(TagEnd::SelfClosing);
28            }
29            if self.lexer.peek('>') {
30                self.parse::<CloseAngle>(Action::TagEnd)?;
31                return Ok(TagEnd::Normal);
32            }
33            self.attr()?;
34        }
35    }
36
37    /// assert this element IS NOT a [`TagEnd::SelfClosing`]
38    pub fn assert_children(&mut self) -> Result<(), DeXmlError> {
39        match self.tag_end()? {
40            TagEnd::Normal => Ok(()),
41            TagEnd::SelfClosing => Err(self.err(Cow::Borrowed(DeXmlError::EXPECTED_CHILDREN))),
42        }
43    }
44
45    /// if the element has a [`TagEnd::SelfClosing`] does nothing
46    /// if the element has a [`TagEnd::Normal`] attempts to parse the closing "\<\/Element\>"
47    ///
48    /// some elements end in self closing tags such as: "\<Element \/\>"
49    /// while others look like: "\<Element\>\<\/Element\>"
50    /// [`Reader::tag_close_infer`] can be used in combination with the output of [`Reader::tag_end`]
51    /// to parse these correctly
52    ///
53    /// e.x:
54    ///
55    /// ```rust,ignore
56    /// let tag_end = reader.tag_end()?;
57    /// // if the element was self closing it does nothing, else parse the closing tag
58    /// reader.tag_close_infer(tag_end)?;
59    /// ```
60    pub fn tag_close_infer(&mut self, tag_end: TagEnd) -> Result<(), DeXmlError> {
61        match tag_end {
62            TagEnd::SelfClosing => Ok(()),
63            TagEnd::Normal => self.close_tag(),
64        }
65    }
66}