parco_xml/dexml/
reader.rs1use std::borrow::Cow;
2
3use crate::{
4 DeXml, DeXmlError,
5 de::AppendPath,
6 dexml::{
7 lex::{CloseAngle, Lexer, OpenAngle, Slash, Text},
8 parse::Action,
9 },
10};
11
12#[derive(Clone, Debug)]
14pub struct Reader<'a> {
15 pub(super) lexer: Lexer<'a>,
16 pub(super) path: String,
17}
18
19impl<'a> Reader<'a> {
20 pub const fn new(xml: &'a str) -> Self {
22 Self {
23 lexer: Lexer::new(xml),
24 path: String::new(),
25 }
26 }
27
28 pub const fn path(&self) -> &str {
30 self.path.as_str()
31 }
32
33 pub fn open_tag(&mut self, tag: &str) -> Result<(), DeXmlError> {
35 self.append_path(AppendPath::Element(tag));
36
37 self.parse::<OpenAngle>(Action::OpenTag)?;
38 let tag_found = self.parse_tag(Action::OpenTag)?;
39
40 match tag_found.0 == tag {
41 true => Ok(()),
42 false => Err(self.err(Cow::Borrowed(DeXmlError::EXPECTED_ELEMENT))),
43 }
44 }
45
46 pub fn close_tag(&mut self) -> Result<(), DeXmlError> {
48 self.parse::<OpenAngle>(Action::CloseTag)?;
49 self.parse::<Slash>(Action::CloseTag)?;
50 self.parse_tag(Action::CloseTag)?;
51 self.parse::<CloseAngle>(Action::CloseTag)?;
52 self.exit_path();
53
54 Ok(())
55 }
56
57 pub fn text(&mut self) -> Result<&'a str, DeXmlError> {
59 self.append_path(AppendPath::Text);
60
61 match self.parse::<Text>(Action::Text) {
62 Ok(Text(text)) => {
63 self.exit_path();
64 Ok(text.trim())
65 }
66 Err(err) => Err(err),
67 }
68 }
69
70 pub fn err(&mut self, message: Cow<'static, str>) -> DeXmlError {
72 DeXmlError {
73 message,
74 path: std::mem::take(&mut self.path),
75 xml: self.lexer.xml().into(),
76 }
77 }
78
79 pub fn visit<T: DeXml<'a>>(&mut self) -> Result<T, DeXmlError> {
83 T::dexml_reader(self)
84 }
85
86 pub fn dexml<T: DeXml<'a>>(&mut self, arg: &'a str) -> Result<T, DeXmlError> {
95 let mut sub_reader = Self {
96 lexer: Lexer::new(arg),
97 path: ::std::mem::take(&mut self.path),
98 };
99 let res = T::dexml_reader(&mut sub_reader)?;
100 self.path = sub_reader.path;
101 Ok(res)
102 }
103}