1use std::fmt;
16use tokenizer::{PeekableTokens, Token};
17use FromTokens;
18use types::CoordType;
19
20#[derive(Default)]
21pub struct Coord<T = f64>
22where T: CoordType,
23{
24 pub x: T,
25 pub y: T,
26 pub z: Option<T>,
27 pub m: Option<T>,
28}
29
30impl<T: CoordType> fmt::Display for Coord<T> {
31 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
32 write!(f, "{} {}", self.x, self.y)?;
33 if let Some(z) = self.z {
34 write!(f, " {}", z)?;
35 }
36 if let Some(m) = self.m {
37 write!(f, " {}", m)?;
38 }
39 Ok(())
40 }
41}
42
43impl<T: CoordType> Coord<T> {
44 pub fn new(x: T, y: T) -> Coord<T> {
45 Coord{x, y, z: None, m: None}
46 }
47}
48
49impl<T: CoordType> FromTokens<T> for Coord<T> {
50 fn from_tokens(tokens: &mut PeekableTokens<T>) -> Result<Self, &'static str> {
51 let x = match tokens.next() {
52 Some(Token::Number(n)) => n,
53 _ => return Err("Expected a number for the X coordinate"),
54 };
55 let y = match tokens.next() {
56 Some(Token::Number(n)) => n,
57 _ => return Err("Expected a number for the Y coordinate"),
58 };
59 Ok(Coord {
60 x: x,
61 y: y,
62 z: None,
63 m: None,
64 })
65 }
66}
67
68#[cfg(test)]
69mod tests {
70 use super::Coord;
71
72 #[test]
73 fn write_2d_coord() {
74 let coord = Coord {
75 x: 10.1,
76 y: 20.2,
77 z: None,
78 m: None,
79 };
80
81 assert_eq!("10.1 20.2", format!("{}", coord));
82 }
83
84 #[test]
85 fn write_3d_coord() {
86 let coord = Coord {
87 x: 10.1,
88 y: 20.2,
89 z: Some(-30.3),
90 m: None,
91 };
92
93 assert_eq!("10.1 20.2 -30.3", format!("{}", coord));
94 }
95
96 #[test]
97 fn write_2d_coord_with_linear_referencing_system() {
98 let coord = Coord {
99 x: 10.1,
100 y: 20.2,
101 z: None,
102 m: Some(10.),
103 };
104
105 assert_eq!("10.1 20.2 10", format!("{}", coord));
106 }
107
108 #[test]
109 fn write_3d_coord_with_linear_referencing_system() {
110 let coord = Coord {
111 x: 10.1,
112 y: 20.2,
113 z: Some(-30.3),
114 m: Some(10.),
115 };
116
117 assert_eq!("10.1 20.2 -30.3 10", format!("{}", coord));
118 }
119}