use errors::*;
use std::io::Read;
use xml::reader::XmlEvent;
use parser::string;
use parser::Context;
use Link;
pub fn consume<R: Read>(context: &mut Context<R>) -> Result<Link> {
let mut link: Link = Default::default();
while let Some(event) = context.reader.next() {
match event.chain_err(|| "error while parsing XML")? {
XmlEvent::StartElement {
name, attributes, ..
} => {
match name.local_name.as_ref() {
"text" => link.text = Some(string::consume(context)?),
"type" => link._type = Some(string::consume(context)?),
"link" => {
let attr = attributes
.into_iter()
.filter(|attr| attr.name.local_name == "href")
.nth(0);
let attr = attr.ok_or("no href attribute on link tag".to_owned())?;
link.href = attr.value;
}
child => Err(Error::from(ErrorKind::InvalidChildElement(
String::from(child),
"link",
)))?,
}
}
XmlEvent::EndElement { .. } => {
return Ok(link);
}
_ => {}
}
}
return Err("no end tag for link".into());
}
#[cfg(test)]
mod tests {
use std::io::BufReader;
use xml::reader::EventReader;
use parser::Context;
use GpxVersion;
use super::consume;
#[test]
fn consume_simple_link() {
let link = consume!(
"<link href='http://example.com'><text>hello</text><type>world</type></link>",
GpxVersion::Gpx11
);
assert!(link.is_ok());
let link = link.unwrap();
assert_eq!(link.href, "http://example.com");
assert!(link.text.is_some());
assert_eq!(link.text.unwrap(), "hello");
assert!(link._type.is_some());
assert_eq!(link._type.unwrap(), "world");
}
#[test]
fn consume_barebones() {
let link = consume!(
"<link href='http://topografix.com'></link>",
GpxVersion::Gpx11
);
assert!(link.is_ok());
let link = link.unwrap();
assert_eq!(link.href, "http://topografix.com");
assert!(link.text.is_none());
assert!(link._type.is_none());
}
#[test]
fn consume_no_href() {
let link = consume!("<link></link>", GpxVersion::Gpx11);
assert!(link.is_err());
}
}