rustical_xml/
de.rs

1use quick_xml::events::{BytesStart, Event};
2use quick_xml::name::ResolveResult;
3use std::io::BufRead;
4pub use xml_derive::XmlDeserialize;
5pub use xml_derive::XmlDocument;
6
7use crate::XmlError;
8use crate::XmlRootTag;
9
10pub trait XmlDeserialize: Sized {
11    fn deserialize<R: BufRead>(
12        reader: &mut quick_xml::NsReader<R>,
13        start: &BytesStart,
14        empty: bool,
15    ) -> Result<Self, XmlError>;
16}
17
18pub trait XmlDocument: XmlDeserialize {
19    fn parse<R: BufRead>(reader: quick_xml::NsReader<R>) -> Result<Self, XmlError>;
20
21    #[inline]
22    fn parse_reader<R: BufRead>(input: R) -> Result<Self, XmlError>
23    where
24        Self: XmlDeserialize,
25    {
26        let mut reader = quick_xml::NsReader::from_reader(input);
27        reader.config_mut().trim_text(true);
28        Self::parse(reader)
29    }
30
31    #[inline]
32    fn parse_str(s: &str) -> Result<Self, XmlError> {
33        Self::parse_reader(s.as_bytes())
34    }
35}
36
37impl<T: XmlRootTag + XmlDeserialize> XmlDocument for T {
38    fn parse<R: BufRead>(mut reader: quick_xml::NsReader<R>) -> Result<Self, XmlError>
39    where
40        Self: XmlDeserialize,
41    {
42        let mut buf = Vec::new();
43        loop {
44            let event = reader.read_event_into(&mut buf)?;
45            let empty = matches!(event, Event::Empty(_));
46            match event {
47                Event::Decl(_) => { /* <?xml ... ?> ignore this */ }
48                Event::Comment(_) => { /*  ignore this */ }
49                Event::Start(start) | Event::Empty(start) => {
50                    let (ns, name) = reader.resolve_element(start.name());
51                    let matches = match (Self::root_ns(), &ns, name) {
52                        // Wrong tag
53                        (_, _, name) if name.as_ref() != Self::root_tag() => false,
54                        // Wrong namespace
55                        (Some(root_ns), ns, _) if &ResolveResult::Bound(root_ns) != ns => false,
56                        _ => true,
57                    };
58                    if !matches {
59                        let root_ns = Self::root_ns();
60                        return Err(XmlError::InvalidTag(
61                            format!("{ns:?}"),
62                            String::from_utf8_lossy(name.as_ref()).to_string(),
63                            format!("{root_ns:?}"),
64                            String::from_utf8_lossy(Self::root_tag()).to_string(),
65                        ));
66                    };
67
68                    return Self::deserialize(&mut reader, &start, empty);
69                }
70                Event::Eof => return Err(XmlError::Eof),
71                _ => return Err(XmlError::UnsupportedEvent("unknown, todo")),
72            };
73        }
74    }
75}
76
77impl XmlDeserialize for () {
78    fn deserialize<R: BufRead>(
79        reader: &mut quick_xml::NsReader<R>,
80        start: &BytesStart,
81        empty: bool,
82    ) -> Result<Self, XmlError> {
83        if empty {
84            return Ok(());
85        }
86        let mut buf = Vec::new();
87        loop {
88            match reader.read_event_into(&mut buf)? {
89                Event::End(e) if e.name() == start.name() => return Ok(()),
90                Event::Eof => return Err(XmlError::Eof),
91                _ => {}
92            };
93        }
94    }
95}