assemblylift_iomod_s3_guest/xml_util/
util.rs1use std::collections::HashMap;
7use std::io;
8use std::iter::Peekable;
9use std::num::ParseIntError;
10use xml;
11use xml::reader::{EventReader, Events, ParserConfig, XmlEvent};
12use xml::writer::EventWriter;
13
14#[derive(Debug)]
16pub struct XmlParseError(pub String);
17
18impl XmlParseError {
19 pub fn new(msg: &str) -> XmlParseError {
20 XmlParseError(msg.to_string())
21 }
22}
23
24pub type XmlStack<'a> = Peekable<Events<&'a [u8]>>;
26
27pub trait Peek {
29 fn peek(&mut self) -> Option<&Result<XmlEvent, xml::reader::Error>>;
30}
31
32pub trait Next {
34 fn next(&mut self) -> Option<Result<XmlEvent, xml::reader::Error>>;
35}
36
37pub struct XmlResponse<'b> {
39 xml_stack: Peekable<Events<&'b [u8]>>, }
41
42impl<'b> XmlResponse<'b> {
43 pub fn new(stack: Peekable<Events<&'b [u8]>>) -> XmlResponse {
44 XmlResponse { xml_stack: stack }
45 }
46}
47
48impl<'b> Peek for XmlResponse<'b> {
49 fn peek(&mut self) -> Option<&Result<XmlEvent, xml::reader::Error>> {
50 while let Some(&Ok(XmlEvent::Whitespace(_))) = self.xml_stack.peek() {
51 self.xml_stack.next();
52 }
53 self.xml_stack.peek()
54 }
55}
56
57impl<'b> Next for XmlResponse<'b> {
58 fn next(&mut self) -> Option<Result<XmlEvent, xml::reader::Error>> {
59 let mut maybe_event;
60 loop {
61 maybe_event = self.xml_stack.next();
62 match maybe_event {
63 Some(Ok(XmlEvent::Whitespace(_))) => {}
64 _ => break,
65 }
66 }
67 maybe_event
68 }
69}
70
71impl From<ParseIntError> for XmlParseError {
72 fn from(_e: ParseIntError) -> XmlParseError {
73 XmlParseError::new("ParseIntError")
74 }
75}
76
77pub fn string_field<T: Peek + Next>(name: &str, stack: &mut T) -> Result<String, XmlParseError> {
79 start_element(name, stack)?;
80 let value = characters(stack)?;
81 end_element(name, stack)?;
82 Ok(value)
83}
84
85pub fn write_characters_element<W>(
86 writer: &mut EventWriter<W>,
87 name: &str,
88 value_str: &str,
89) -> Result<(), xml::writer::Error>
90where
91 W: io::Write,
92{
93 writer.write(xml::writer::XmlEvent::start_element(name))?;
94 writer.write(xml::writer::XmlEvent::characters(value_str))?;
95 writer.write(xml::writer::XmlEvent::end_element())
96}
97
98pub fn deserialize_primitive<T: Peek + Next, U>(
99 tag_name: &str,
100 stack: &mut T,
101 deserialize: fn(String) -> Result<U, XmlParseError>,
102) -> Result<U, XmlParseError> {
103 start_element(tag_name, stack)?;
104 let obj = deserialize(characters(stack)?)?;
105 end_element(tag_name, stack)?;
106
107 Ok(obj)
108}
109
110pub fn characters<T: Peek + Next>(stack: &mut T) -> Result<String, XmlParseError> {
112 {
113 let current = stack.peek();
117 if let Some(&Ok(XmlEvent::EndElement { .. })) = current {
118 return Ok("".to_string());
119 }
120 }
121 match stack.next() {
122 Some(Ok(XmlEvent::Characters(data))) | Some(Ok(XmlEvent::CData(data))) => Ok(data),
123 _ => Err(XmlParseError::new("Expected characters")),
124 }
125}
126
127pub fn peek_at_name<T: Peek + Next>(stack: &mut T) -> Result<String, XmlParseError> {
129 let current = stack.peek();
130 if let Some(&Ok(XmlEvent::StartElement { ref name, .. })) = current {
131 Ok(name.local_name.to_string())
132 } else {
133 Ok("".to_string())
134 }
135}
136
137pub fn start_element<T: Peek + Next>(
139 element_name: &str,
140 stack: &mut T,
141) -> Result<HashMap<String, String>, XmlParseError> {
142 let next = stack.next();
143
144 if let Some(Ok(XmlEvent::StartElement {
145 name, attributes, ..
146 })) = next
147 {
148 if name.local_name == element_name {
149 let mut attr_map = HashMap::new();
150 for attr in attributes {
151 attr_map.insert(attr.name.local_name, attr.value);
152 }
153 Ok(attr_map)
154 } else {
155 Err(XmlParseError::new(&format!(
156 "START Expected {} got {}",
157 element_name, name.local_name
158 )))
159 }
160 } else {
161 Err(XmlParseError::new(&format!(
162 "Expected StartElement {} got {:#?}",
163 element_name, next
164 )))
165 }
166}
167
168pub fn end_element<T: Peek + Next>(element_name: &str, stack: &mut T) -> Result<(), XmlParseError> {
170 let next = stack.next();
171 if let Some(Ok(XmlEvent::EndElement { name, .. })) = next {
172 if name.local_name == element_name {
173 Ok(())
174 } else {
175 Err(XmlParseError::new(&format!(
176 "END Expected {} got {}",
177 element_name, name.local_name
178 )))
179 }
180 } else {
181 Err(XmlParseError::new(&format!(
182 "Expected EndElement {} got {:?}",
183 element_name, next
184 )))
185 }
186}
187
188pub fn skip_tree<T: Peek + Next>(stack: &mut T) {
190 let mut deep: usize = 0;
191
192 loop {
193 match stack.next() {
194 None => break,
195 Some(Ok(XmlEvent::StartElement { .. })) => deep += 1,
196 Some(Ok(XmlEvent::EndElement { .. })) => {
197 if deep > 1 {
198 deep -= 1;
199 } else {
200 break;
201 }
202 }
203 _ => (),
204 }
205 }
206}
207
208pub fn find_start_element<T: Peek + Next>(stack: &mut T) {
212 loop {
213 match stack.peek() {
214 Some(&Ok(XmlEvent::StartElement { .. })) => break,
215 Some(&Ok(_)) => {
216 stack.next().unwrap().unwrap();
217 }
218 Some(&Err(_)) => break,
219 None => break,
220 }
221 }
222}
223
224pub fn deserialize_elements<T, S, F>(
225 tag_name: &str,
226 stack: &mut T,
227 mut handle_element: F,
228) -> Result<S, XmlParseError>
229where
230 T: Peek + Next,
231 S: Default,
232 F: FnMut(&str, &mut T, &mut S) -> Result<(), XmlParseError>,
233{
234 let mut obj = S::default();
235
236 start_element(tag_name, stack)?;
237
238 loop {
239 match stack.peek() {
240 Some(&Ok(XmlEvent::EndElement { .. })) => break,
241 Some(&Ok(XmlEvent::StartElement { ref name, .. })) => {
242 let local_name = name.local_name.to_owned();
243 handle_element(&local_name, stack, &mut obj)?;
244 }
245 _ => {
246 stack.next();
247 }
248 }
249 }
250
251 end_element(tag_name, stack)?;
252
253 Ok(obj)
254}