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*/