1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
use crate::{
error::Error,
metas::{DataKind, FieldDef, PcdMeta, Schema, TypeKind, ValueKind, ViewPoint},
};
use anyhow::Result;
use std::{collections::HashSet, io::prelude::*};
pub fn load_meta<R: BufRead>(reader: &mut R, line_count: &mut usize) -> Result<PcdMeta> {
let mut get_meta_line = |expect_entry: &str| -> Result<_> {
loop {
let mut line = String::new();
let read_size = reader.read_line(&mut line)?;
*line_count += 1;
if read_size == 0 {
return Err(Error::new_parse_error(*line_count, "Unexpected end of file").into());
}
let line_stripped = match line.split('#').next() {
Some("") => continue,
Some(remaining) => remaining,
None => continue,
};
let tokens: Vec<String> = line_stripped
.split_ascii_whitespace()
.map(|s| s.to_owned())
.collect();
if tokens.is_empty() {
let desc = format!("Cannot parse empty line at line {}", *line_count + 1);
return Err(Error::new_parse_error(*line_count, &desc).into());
}
if tokens[0] != expect_entry {
let desc = format!(
"Expect {:?} entry, found {:?} at line {}",
expect_entry,
tokens[0],
*line_count + 1
);
return Err(Error::new_parse_error(*line_count, &desc).into());
}
return Ok(tokens);
}
};
let meta_version = {
let tokens = get_meta_line("VERSION")?;
if tokens.len() == 2 {
match tokens[1].as_str() {
"0.7" => String::from("0.7"),
".7" => String::from("0.7"),
_ => {
let desc = format!(
"Unsupported version {:?}. Supported versions are: 0.7",
tokens[1]
);
return Err(Error::new_parse_error(*line_count, &desc).into());
}
}
} else {
return Err(
Error::new_parse_error(*line_count, "VERSION line is not understood").into(),
);
}
};
let meta_fields = {
let tokens = get_meta_line("FIELDS")?;
if tokens.len() == 1 {
return Err(
Error::new_parse_error(*line_count, "FIELDS line is not understood").into(),
);
}
let mut name_set = HashSet::new();
let mut field_names: Vec<String> = vec![];
for tk in tokens[1..].iter() {
let field = tk;
if name_set.contains(field) {
let desc = format!("field name {:?} is specified more than once", field);
return Err(Error::new_parse_error(*line_count, &desc).into());
}
name_set.insert(field);
field_names.push(field.to_owned());
}
field_names
};
let meta_size = {
let tokens = get_meta_line("SIZE")?;
if tokens.len() == 1 {
return Err(Error::new_parse_error(*line_count, "SIZE line is not understood").into());
}
let mut sizes = vec![];
for tk in tokens[1..].iter() {
let size: u64 = tk.parse()?;
sizes.push(size);
}
sizes
};
let meta_type = {
let tokens = get_meta_line("TYPE")?;
if tokens.len() == 1 {
return Err(Error::new_parse_error(*line_count, "TYPE line is not understood").into());
}
let mut types = vec![];
for type_char in tokens[1..].iter() {
let type_ = match type_char.as_str() {
"I" => TypeKind::I,
"U" => TypeKind::U,
"F" => TypeKind::F,
_ => {
let desc = format!("Invalid type character {:?} in TYPE line", type_char);
return Err(Error::new_parse_error(*line_count, &desc).into());
}
};
types.push(type_);
}
types
};
let meta_count = {
let tokens = get_meta_line("COUNT")?;
if tokens.len() == 1 {
return Err(Error::new_parse_error(*line_count, "COUNT line is not understood").into());
}
let mut counts = vec![];
for tk in tokens[1..].iter() {
let count: u64 = tk.parse()?;
counts.push(count);
}
counts
};
let meta_width = {
let tokens = get_meta_line("WIDTH")?;
if tokens.len() != 2 {
return Err(Error::new_parse_error(*line_count, "WIDTH line is not understood").into());
}
let width: u64 = tokens[1].parse()?;
width
};
let meta_height = {
let tokens = get_meta_line("HEIGHT")?;
if tokens.len() != 2 {
return Err(
Error::new_parse_error(*line_count, "HEIGHT line is not understood").into(),
);
}
let height: u64 = tokens[1].parse()?;
height
};
let meta_viewpoint = {
let tokens = get_meta_line("VIEWPOINT")?;
if tokens.len() != 8 {
return Err(
Error::new_parse_error(*line_count, "VIEWPOINT line is not understood").into(),
);
}
let tx = tokens[1].parse()?;
let ty = tokens[2].parse()?;
let tz = tokens[3].parse()?;
let qw = tokens[4].parse()?;
let qx = tokens[5].parse()?;
let qy = tokens[6].parse()?;
let qz = tokens[7].parse()?;
ViewPoint {
tx,
ty,
tz,
qw,
qx,
qy,
qz,
}
};
let meta_points = {
let tokens = get_meta_line("POINTS")?;
if tokens.len() != 2 {
return Err(
Error::new_parse_error(*line_count, "POINTS line is not understood").into(),
);
}
let count: u64 = tokens[1].parse()?;
count
};
let meta_data = {
let tokens = get_meta_line("DATA")?;
if tokens.len() != 2 {
return Err(Error::new_parse_error(*line_count, "DATA line is not understood").into());
}
match tokens[1].as_str() {
"ascii" => DataKind::Ascii,
"binary" => DataKind::Binary,
_ => {
return Err(
Error::new_parse_error(*line_count, "DATA line is not understood").into(),
);
}
}
};
if meta_size.len() != meta_fields.len() {
return Err(
Error::new_parse_error(*line_count, "SIZE entry conflicts with FIELD entry").into(),
);
}
if meta_type.len() != meta_fields.len() {
return Err(
Error::new_parse_error(*line_count, "TYPE entry conflicts with FIELD entry").into(),
);
}
if meta_count.len() != meta_fields.len() {
return Err(
Error::new_parse_error(*line_count, "COUNT entry conflicts with FIELD entry").into(),
);
}
let field_defs: Result<Schema> = {
meta_fields
.iter()
.zip(meta_type.iter())
.zip(meta_size.iter())
.zip(meta_count.iter())
.map(|(((name, type_), size), &count)| {
let kind = match (type_, size) {
(TypeKind::U, 1) => ValueKind::U8,
(TypeKind::U, 2) => ValueKind::U16,
(TypeKind::U, 4) => ValueKind::U32,
(TypeKind::I, 1) => ValueKind::I8,
(TypeKind::I, 2) => ValueKind::I16,
(TypeKind::I, 4) => ValueKind::I32,
(TypeKind::F, 4) => ValueKind::F32,
(TypeKind::F, 8) => ValueKind::F64,
_ => {
let desc =
format!("Field type {:?} with size {} is not supported", type_, size);
return Err(Error::new_parse_error(*line_count, &desc).into());
}
};
let meta = FieldDef {
name: name.to_owned(),
kind,
count,
};
Ok(meta)
})
.collect()
};
let meta = PcdMeta {
version: meta_version,
field_defs: field_defs?,
width: meta_width,
height: meta_height,
viewpoint: meta_viewpoint,
num_points: meta_points,
data: meta_data,
};
Ok(meta)
}