Skip to main content

parco_xml/dexml/
tag.rs

1use crate::{
2    DeXmlError,
3    dexml::{
4        lex::{Colon, Ident, OpenAngle, Slash},
5        parse::Action,
6        reader::Reader,
7    },
8};
9
10pub struct Tag<'a>(pub &'a str);
11
12/// a peeked tag either Open i.e "\<Element" or "\<\/Element"
13pub enum PeekedTag<'a> {
14    /// open tag "\<Element"
15    Open(&'a str),
16    /// close tag "\<\/Element"
17    Close(&'a str),
18}
19
20impl<'a> Reader<'a> {
21    pub(crate) fn parse_tag(&mut self, action: Action) -> Result<Tag<'a>, DeXmlError> {
22        let ident: Ident = self.parse(action)?;
23
24        match self.lexer.peek(':') {
25            true => {
26                self.parse::<Colon>(action)?;
27                let ident: Ident = self.parse(action)?;
28                Ok(Tag(ident.0))
29            }
30            false => Ok(Tag(ident.0)),
31        }
32    }
33
34    /// inspect the next tag, can be used for parsing [`std::vec::Vec`]
35    pub fn peek_tag(&mut self) -> Option<&'a str> {
36        let mut lexer = self.lexer.clone();
37
38        lexer.token::<OpenAngle>().ok()?;
39
40        let ident = lexer.token::<Ident>().ok()?;
41        if lexer.peek(':') {
42            lexer.token::<Colon>().ok()?;
43            let id = lexer.token::<Ident>().ok()?;
44            return Some(id.0);
45        }
46
47        Some(ident.0)
48    }
49
50    /// similar to [`Reader::peek_tag`] but inspects the next closing tag i.e "\<\/tag"
51    pub fn peek_closing_tag(&mut self) -> Option<&'a str> {
52        let mut lexer = self.lexer.clone();
53
54        lexer.token::<OpenAngle>().ok()?;
55        lexer.token::<Slash>().ok()?;
56
57        let ident = lexer.token::<Ident>().ok()?;
58        if lexer.peek(':') {
59            lexer.token::<Colon>().ok()?;
60            let id = lexer.token::<Ident>().ok()?;
61            return Some(id.0);
62        }
63
64        Some(ident.0)
65    }
66
67    /// similar to [`Reader::peek_tag`] but accepts either an opening tag or closing tag
68    pub fn peek_open_or_closing_tag(&mut self) -> Option<PeekedTag<'a>> {
69        let mut lexer = self.lexer.clone();
70
71        lexer.token::<OpenAngle>().ok()?;
72        let is_close = match lexer.peek('/') {
73            true => {
74                lexer.token::<Slash>().ok()?;
75                true
76            }
77            false => false,
78        };
79
80        let ident = lexer.token::<Ident>().ok()?;
81        let tag = match lexer.peek(':') {
82            true => {
83                lexer.token::<Colon>().ok()?;
84                let id = lexer.token::<Ident>().ok()?;
85                id.0
86            }
87            false => ident.0,
88        };
89
90        match is_close {
91            true => Some(PeekedTag::Close(tag)),
92            false => Some(PeekedTag::Open(tag)),
93        }
94    }
95}