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 Ok(())
54 }
55
56 pub fn text(&mut self) -> Result<&'a str, DeXmlError> {
58 self.append_path(AppendPath::Text);
59
60 match self.parse::<Text>(Action::Text) {
61 Ok(Text(text)) => {
62 self.exit_path();
63 Ok(text.trim())
64 }
65 Err(err) => Err(err),
66 }
67 }
68
69 pub fn err(&mut self, message: Cow<'static, str>) -> DeXmlError {
71 DeXmlError {
72 message,
73 path: std::mem::take(&mut self.path),
74 xml: self.lexer.xml().into(),
75 }
76 }
77
78 pub fn visit<T: DeXml<'a>>(&mut self) -> Result<T, DeXmlError> {
82 T::dexml_reader(self)
83 }
84
85 pub fn dexml<T: DeXml<'a>>(&mut self, arg: &'a str) -> Result<T, DeXmlError> {
94 let mut sub_reader = Self {
95 lexer: Lexer::new(arg),
96 path: ::std::mem::take(&mut self.path),
97 };
98 let res = T::dexml_reader(&mut sub_reader)?;
99 self.path = sub_reader.path;
100 Ok(res)
101 }
102}