use errors::*;
use std::io::Read;
use xml::reader::XmlEvent;
use parser::verify_starting_tag;
use parser::Context;
pub fn consume<R: Read>(context: &mut Context<R>, tagname: &'static str) -> Result<String> {
let mut string: Option<String> = None;
verify_starting_tag(context, tagname)?;
for event in context.reader() {
match event.chain_err(|| "error while parsing XML")? {
XmlEvent::StartElement { ref name, .. } => {
bail!(ErrorKind::InvalidChildElement(
name.local_name.clone(),
tagname
));
}
XmlEvent::Characters(content) => string = Some(content),
XmlEvent::EndElement { ref name } => {
ensure!(
name.local_name == tagname,
ErrorKind::InvalidClosingTag(name.local_name.clone(), tagname)
);
return string.ok_or("no content inside string".into());
}
_ => {}
}
}
bail!(ErrorKind::MissingClosingTag(tagname));
}
#[cfg(test)]
mod tests {
use std::io::BufReader;
use super::consume;
use GpxVersion;
#[test]
fn consume_simple_string() {
let result = consume!("<string>hello world</string>", GpxVersion::Gpx11, "string");
assert!(result.is_ok());
assert_eq!(result.unwrap(), "hello world");
}
#[test]
fn consume_new_tag() {
let result = consume!("<foo>bar<baz></baz></foo>", GpxVersion::Gpx11, "foo");
assert!(result.is_err());
}
#[test]
fn consume_start_tag() {
let result = consume!("bar</foo>", GpxVersion::Gpx11, "foo");
assert!(result.is_err());
}
#[test]
fn consume_end_tag() {
let result = consume!("<foo>bar", GpxVersion::Gpx11, "foo");
assert!(result.is_err());
}
#[test]
fn consume_no_body() {
let result = consume!("<foo></foo>", GpxVersion::Gpx11, "foo");
assert!(result.is_err());
}
#[test]
fn consume_different_ending_tag() {
let result = consume!("<foo></foobar>", GpxVersion::Gpx11, "foo");
assert!(result.is_err());
}
}