inkml/
trace.rs

1//use xsd;
2use super::{Point, ParseError, ParseResult, wsp}; 
3
4//mod channel;
5
6#[derive(Debug, PartialEq)]
7enum TraceType { PenDown, PenUp, Indeterminate }
8
9impl Default for TraceType {
10    fn default() -> Self { TraceType::PenDown }
11}
12
13#[derive(Debug, PartialEq)]
14pub enum TraceContinuation {
15    Begin,
16    //Middle(xsd::AnyUri),
17    Middle(String),
18    //End(xsd::AnyUri)
19    End(String),
20}
21
22#[derive(Debug, PartialEq)]
23pub struct Trace {
24    
25    /// List of data points that describe this trace.
26    pub content: Vec<Point>,
27    
28	/* ATTRIBUTES */
29	
30	/// The identifier for this trace.
31	/// Required: no, Default: none
32	//id: Option<xsd::ID>,
33	id: Option<String>,
34	
35	/// The type of this trace.
36	/// Required: no, Default: "penDown"
37	kind: Option<TraceType>,
38	
39	/// This attribute indicates whether this trace is a trace fragment, and if
40	/// so, where this trace is located in the set of continuation traces.
41	/// Required: no, Default: none
42	continuation: Option<TraceContinuation>,
43	
44	/// The context for this trace. Any values in this context over-ride the
45	/// values in the inherited context.
46	/// Required: no, Default: "#DefaultContext," unless this <trace> is
47	/// contained within a <traceGroup>, then inherit from the <traceGroup>.
48	//context_ref: Option<xsd::AnyUri>,
49	context_ref: Option<String>,
50	
51	/// The brush for this trace.
52	/// Required: no, Default: Inherited from context.
53	//brush_ref: Option<xsd::AnyUri>,
54	brush_ref: Option<String>,
55	
56	/// The duration of this trace, in milliseconds.
57	/// Required: no, Default: none
58	//duration: Option<xsd::Decimal>,
59	duration: Option<f64>,
60	
61	/// The relative timestamp or time-of-day for the start of this trace, in
62	/// milliseconds.
63	/// Required: no, Default: none
64	//time_offset: Option<xsd::Decimal>,
65	time_offset: Option<f64>,
66}
67
68impl Trace {
69    pub fn new(points: Vec<Point>) -> Trace {
70        Trace {
71            content: points,
72            id: None,
73            kind: None,
74            continuation: None,
75            context_ref: None,
76            brush_ref: None,
77            duration: None,
78            time_offset: None,
79        }
80    }
81    // trace ::= point ("," point)* ","? wsp*
82    //       ::= <0> point <1> ("," point)* <2> ","? <3> wsp* <4>
83    // 0 -> {point -> 1}
84    // 1 -> {"," -> point -> 1, "" -> 2}
85    // 2 -> {"," -> 3, "" -> 3}
86    // 3 -> {wsp -> 3, "" -> 4}
87    // 4 -> {}
88    pub fn parse(input: &str) -> ParseResult<(&str, Self)> {
89        let mut points = Vec::new();
90        
91        // <0>
92        // point
93        let (mut input, point) = Point::parse(input)?;
94        points.push(point);
95        
96        // <1>
97        // ("," point)*
98        loop {
99            let backtrack = input;
100            
101            // <1> "" -> 2
102            if input.is_empty() || input.starts_with(wsp) { break }
103            
104            // ","
105            if !input.starts_with(',') {
106                return Err(ParseError::UnexpectedValue(input));
107            }
108            input = &input[1..];
109            
110            // point
111            match Point::parse(input) {
112                Ok((i, point)) => {
113                    input = i;
114                    points.push(point);
115                }
116                // <1> "" -> "," -> 3
117                Err(_) => {
118                    input = backtrack;
119                    break;
120                }
121            }
122        }
123        
124        // <2>
125        // ","?
126        if input.starts_with(',') {
127            input = &input[1..];
128        }
129        
130        // <3>
131        // wsp*
132        input = input.trim_left_matches(wsp);
133        
134        // <4>
135        Ok((input, Trace::new(points)))
136    }
137}
138
139#[cfg(test)]
140mod test {
141    use super::Trace;
142    use super::super::{Point, Value};
143    
144    #[test]
145    #[should_panic]
146    fn empty_string() {
147        Trace::parse("").unwrap();
148    }
149    
150    #[test]
151    fn single() {
152        let expect = ("", Trace::new(vec![Point(vec![Value::Inferred])]));
153        assert_eq!(expect, Trace::parse("*").unwrap());
154        assert_eq!(expect, Trace::parse("*,").unwrap());
155        assert_eq!(expect, Trace::parse("* ").unwrap());
156        assert_eq!(expect, Trace::parse("*, ").unwrap());
157    }
158    
159    #[test]
160    fn many() {
161        let expect = ("", Trace::new(vec![
162            Point(vec![Value::Inferred]),
163            Point(vec![Value::Inferred])
164        ]));
165        assert_eq!(expect, Trace::parse("*,*").unwrap());
166        assert_eq!(expect, Trace::parse("*,*,").unwrap());
167        assert_eq!(expect, Trace::parse("*,* ").unwrap());
168        assert_eq!(expect, Trace::parse("*,*, ").unwrap());
169    }
170}
171
172
173
174
175/*
176pub struct TraceFormat {
177	/// The unique identifier for this trace format.
178	/// Required: no, Default: none
179	//id: Option<xsd::ID>,
180	id: Option<String>,
181	
182	channels: Vec<Channel>,
183	intermittent_channels: Vec<IntermittentChannel>,
184}
185*/