Skip to content

Commit

Permalink
Handle the GPX version attribute
Browse files Browse the repository at this point in the history
Issue: #5
PR: #6
  • Loading branch information
hfiguiere authored and brendanashworth committed Mar 10, 2018
1 parent 6e07049 commit 9680234
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 14 deletions.
69 changes: 56 additions & 13 deletions src/parser/gpx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use parser::metadata;
use parser::waypoint;

use Gpx;
use GpxVersion;

enum ParseEvent {
StartMetadata,
Expand All @@ -20,6 +21,15 @@ enum ParseEvent {
EndGpx,
}

/// Convert the version string to the version enum
fn version_string_to_version(version_str: &str) -> Result<GpxVersion> {
match version_str {
"1.0" => Ok(GpxVersion::Gpx10),
"1.1" => Ok(GpxVersion::Gpx11),
version => Err(Error::from(format!("Unknown version {}", version))),
}
}

/// consume consumes an entire GPX element.
pub fn consume<R: Read>(reader: &mut Peekable<Events<R>>) -> Result<Gpx> {
let mut gpx: Gpx = Default::default();
Expand All @@ -31,18 +41,34 @@ pub fn consume<R: Read>(reader: &mut Peekable<Events<R>>) -> Result<Gpx> {
let event: Result<ParseEvent> = {
if let Some(next) = reader.peek() {
match next {
&Ok(XmlEvent::StartElement { ref name, .. }) => {
match name.local_name.as_ref() {
"metadata" => Ok(ParseEvent::StartMetadata),
"trk" => Ok(ParseEvent::StartTrack),
"wpt" => Ok(ParseEvent::StartWaypoint),
"gpx" => Ok(ParseEvent::Ignore),
child => Err(Error::from(ErrorKind::InvalidChildElement(
String::from(child),
"gpx",
)))?,
&Ok(XmlEvent::StartElement {
ref name,
ref attributes,
..
}) => match name.local_name.as_ref() {
"metadata" => Ok(ParseEvent::StartMetadata),
"trk" => Ok(ParseEvent::StartTrack),
"wpt" => Ok(ParseEvent::StartWaypoint),
"gpx" => {
if let Ok(version) = attributes
.iter()
.filter(|attr| attr.name.local_name == "version")
.nth(0)
.ok_or("no version found".to_owned())
{
gpx.version = version_string_to_version(&version.value)?;
Ok(ParseEvent::Ignore)
} else {
Err(Error::from(ErrorKind::InvalidElementLacksAttribute(
"version",
)))
}
}
}
child => Err(Error::from(ErrorKind::InvalidChildElement(
String::from(child),
"gpx",
)))?,
},

&Ok(XmlEvent::EndElement { .. }) => Ok(ParseEvent::EndGpx),

Expand Down Expand Up @@ -87,20 +113,36 @@ mod tests {
use xml::reader::EventReader;
use geo::Point;

use GpxVersion;

use super::consume;

#[test]
fn consume_gpx() {
let gpx = consume!("<gpx></gpx>");
let gpx = consume!("<gpx version=\"1.1\"></gpx>");

assert!(gpx.is_ok());
}

#[test]
fn consume_gpx_no_version() {
let gpx = consume!("<gpx></gpx>");

assert!(gpx.is_err());
}

#[test]
fn consume_gpx_version_error() {
let gpx = consume!("<gpx version=\"1.2\"></gpx>");

assert!(gpx.is_err());
}

#[test]
fn consume_gpx_full() {
let gpx = consume!(
"
<gpx>
<gpx version=\"1.0\">
<trk></trk>
<wpt lat=\"1.23\" lon=\"2.34\"></wpt>
<wpt lon=\"10.256\" lat=\"-81.324\">
Expand All @@ -113,6 +155,7 @@ mod tests {
assert!(gpx.is_ok());
let gpx = gpx.unwrap();

assert_eq!(gpx.version, GpxVersion::Gpx10);
assert_eq!(gpx.tracks.len(), 1);

assert_eq!(gpx.waypoints.len(), 2);
Expand Down
16 changes: 15 additions & 1 deletion src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,24 @@ use geo::{Bbox, LineString, MultiLineString, Point};
use chrono::DateTime;
use chrono::prelude::Utc;

#[derive(Clone, Debug, PartialEq)]
pub enum GpxVersion {
Unknown,
Gpx10,
Gpx11,
}

impl Default for GpxVersion {
fn default() -> GpxVersion {
GpxVersion::Unknown
}
}

/// Gpx is the root element in the XML file.
#[derive(Clone, Default, Debug)]
pub struct Gpx {
pub version: String,
/// Version of the Gpx file.
pub version: GpxVersion,

/// Metadata about the file.
pub metadata: Option<Metadata>,
Expand Down

0 comments on commit 9680234

Please sign in to comment.