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}