1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
use {
quick_xml::{
events::{BytesEnd as XmlBytesEnd, BytesStart as XmlBytesStart, Event as XmlEvent},
Error as XmlError, Reader as XmlReader,
},
std::{error::Error as StdError, io::BufRead, str::FromStr},
};
use displaydoc::Display;
use thiserror::Error;
#[derive(Debug, Display, Error)]
pub enum Error {
Xml(#[from] XmlError),
Generic(#[from] Box<dyn StdError + Send + Sync>),
ExpectedTag(String, String),
ExpectedEndTag(String, String),
MissingTag(String),
MissingEndTag(String),
MissingText,
MissingAttribute(String),
ExpectedAttribute(String, String),
}
pub type Result<T> = std::result::Result<T, Error>;
pub fn expect_start<'a, 'b, 'c, B: BufRead>(
key: &'a str,
reader: &'b mut XmlReader<B>,
buf: &'c mut Vec<u8>,
) -> Result<XmlBytesStart<'c>> {
if let Ok(XmlEvent::Start(e)) = reader.read_event(buf) {
if e.name() == key.as_bytes() {
Ok(e)
} else {
Err(Error::ExpectedTag(
key.to_owned(),
reader.decode(e.name()).into_owned(),
))
}
} else {
Err(Error::MissingTag(key.to_owned()))
}
}
pub fn expect_end<'a, 'b, 'c, B: BufRead>(
key: &'a str,
reader: &'b mut XmlReader<B>,
buf: &'c mut Vec<u8>,
) -> Result<XmlBytesEnd<'c>> {
if let Ok(XmlEvent::End(e)) = reader.read_event(buf) {
if e.name() == key.as_bytes() {
Ok(e)
} else {
Err(Error::ExpectedEndTag(
key.to_owned(),
reader.decode(e.name()).into_owned(),
))
}
} else {
Err(Error::MissingEndTag(key.to_owned()))
}
}
pub fn expect_text<B: BufRead>(reader: &mut XmlReader<B>, buf: &mut Vec<u8>) -> Result<String> {
if let Ok(XmlEvent::Text(e)) = reader.read_event(buf) {
let text = e.unescape_and_decode(reader)?;
Ok(text)
} else {
Err(Error::MissingText)
}
}
pub fn expect_attribute<T: FromStr, B: BufRead>(
key: &str,
reader: &XmlReader<B>,
event: &XmlBytesStart,
) -> Result<T>
where
<T as FromStr>::Err: std::error::Error + Send + Sync + Sized + 'static,
{
let attr = event
.attributes()
.next()
.ok_or_else(|| Error::MissingAttribute(key.to_owned()))??;
if attr.key == key.as_bytes() {
let attr_unesc = attr.unescaped_value()?;
let attr_str = reader.decode(&attr_unesc);
let value = attr_str.parse().map_err(|e| {
let b: Box<dyn StdError + Sync + Send> = Box::new(e);
b
})?;
Ok(value)
} else {
Err(Error::ExpectedAttribute(
key.to_owned(),
reader.decode(attr.key).into_owned(),
))
}
}