1# or [PcdSerialize](crate::record::PcdSerialize)
6respectively.
7
8These traits are not intended to implemented manually.
9Please use derive macro instead. For example,
10
11"##]
12#![cfg_attr(
13 feature = "derive",
14 doc = r##"
15```rust
16use pcd_rs::{PcdDeserialize, PcdSerialize};
17
18#[derive(PcdDeserialize, PcdSerialize)]
19pub struct TimestampedPoint {
20 x: f32,
21 y: f32,
22 z: f32,
23 timestamp: u32,
24}
25```
26"##
27)]
28# allows fields with either primitive type,
32array of primitive type or [Vec](<std::vec::Vec>) of primitive type.
33
34[PcdSerialize](crate::record::PcdSerialize) allows fields with either primitive type or
35array of primitive type. The [Vec](<std::vec::Vec>) is ruled out since the length
36is not determined in compile-time.
37
38Make sure struct field names match the `FIELDS` header in PCD data.
39Otherwise it panics at runtime. You can specify the exact name in header or bypass name check
40with attributes. The name check are automatically disabled for tuple structs.
41"##]
42#![cfg_attr(
43 feature = "derive",
44 doc = r##"
45```rust
46use pcd_rs::PcdDeserialize;
47
48#[derive(PcdDeserialize)]
49pub struct TimestampedPoint {
50 x: f32,
51 y: f32,
52 z: f32,
53 #[pcd(rename = "true_name")]
54 rust_name: u32,
55 #[pcd(ignore)]
56 whatever_name: u32,
57}
58```
59"##
60)]
61use crate::{
62 error::Error,
63 metas::{FieldDef, Schema, ValueKind},
64 traits::Value,
65 Result,
66};
67use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
68use itertools::Itertools;
69use num_traits::NumCast;
70use std::io::prelude::*;
71
72pub trait PcdDeserialize: Sized {
80 fn is_dynamic() -> bool;
81 fn read_spec() -> Vec<(Option<String>, ValueKind, Option<usize>)>;
82 fn read_chunk<R: BufRead>(reader: &mut R, field_defs: &Schema) -> Result<Self>;
83 fn read_line<R: BufRead>(reader: &mut R, field_defs: &Schema) -> Result<Self>;
84}
85
86pub trait PcdSerialize: Sized {
94 fn is_dynamic() -> bool;
95 fn write_spec() -> Schema;
96 fn write_chunk<R: Write + Seek>(&self, writer: &mut R, spec: &Schema) -> Result<()>;
97 fn write_line<R: Write + Seek>(&self, writer: &mut R, spec: &Schema) -> Result<()>;
98}
99
100#[derive(Debug, Clone, PartialEq)]
104pub enum Field {
105 I8(Vec<i8>),
106 I16(Vec<i16>),
107 I32(Vec<i32>),
108 I64(Vec<i64>),
109 U8(Vec<u8>),
110 U16(Vec<u16>),
111 U32(Vec<u32>),
112 U64(Vec<u64>),
113 F32(Vec<f32>),
114 F64(Vec<f64>),
115}
116
117impl Field {
118 pub fn kind(&self) -> ValueKind {
119 use Field as F;
120 use ValueKind as K;
121
122 match self {
123 F::I8(_) => K::I8,
124 F::I16(_) => K::I16,
125 F::I32(_) => K::I32,
126 F::I64(_) => K::I64,
127 F::U8(_) => K::U8,
128 F::U16(_) => K::U16,
129 F::U32(_) => K::U32,
130 F::U64(_) => K::U64,
131 F::F32(_) => K::F32,
132 F::F64(_) => K::F64,
133 }
134 }
135
136 pub fn count(&self) -> usize {
137 use Field as F;
138
139 match self {
140 F::I8(values) => values.len(),
141 F::I16(values) => values.len(),
142 F::I32(values) => values.len(),
143 F::I64(values) => values.len(),
144 F::U8(values) => values.len(),
145 F::U16(values) => values.len(),
146 F::U32(values) => values.len(),
147 F::U64(values) => values.len(),
148 F::F32(values) => values.len(),
149 F::F64(values) => values.len(),
150 }
151 }
152
153 pub fn to_value<T>(&self) -> Option<T>
154 where
155 T: Value + NumCast,
156 {
157 use Field as F;
158
159 if T::KIND != self.kind() {
160 return None;
161 }
162
163 Some(match self {
164 F::I8(v) => match &**v {
165 &[t] => T::from(t)?,
166 _ => return None,
167 },
168 F::I16(v) => match &**v {
169 &[t] => T::from(t)?,
170 _ => return None,
171 },
172 F::I32(v) => match &**v {
173 &[t] => T::from(t)?,
174 _ => return None,
175 },
176 F::I64(v) => match &**v {
177 &[t] => T::from(t)?,
178 _ => return None,
179 },
180 F::U8(v) => match &**v {
181 &[t] => T::from(t)?,
182 _ => return None,
183 },
184 F::U16(v) => match &**v {
185 &[t] => T::from(t)?,
186 _ => return None,
187 },
188 F::U32(v) => match &**v {
189 &[t] => T::from(t)?,
190 _ => return None,
191 },
192 F::U64(v) => match &**v {
193 &[t] => T::from(t)?,
194 _ => return None,
195 },
196 F::F32(v) => match &**v {
197 &[t] => T::from(t)?,
198 _ => return None,
199 },
200 F::F64(v) => match &**v {
201 &[t] => T::from(t)?,
202 _ => return None,
203 },
204 })
205 }
206}
207
208#[derive(Debug, Clone, PartialEq)]
210pub struct DynRecord(pub Vec<Field>);
211
212impl DynRecord {
213 pub fn is_schema_consistent(&self, schema: &Schema) -> bool {
214 if self.0.len() != schema.len() {
215 return false;
216 }
217
218 self.0
219 .iter()
220 .zip(schema.iter())
221 .all(|(field, schema_field)| {
222 use Field as F;
223 use ValueKind as K;
224
225 if field.count() != schema_field.count as usize {
226 return false;
227 }
228
229 matches!(
230 (field, schema_field.kind),
231 (F::I8(_), K::I8)
232 | (F::I16(_), K::I16)
233 | (F::I32(_), K::I32)
234 | (F::I64(_), K::I64)
235 | (F::U8(_), K::U8)
236 | (F::U16(_), K::U16)
237 | (F::U32(_), K::U32)
238 | (F::U64(_), K::U64)
239 | (F::F32(_), K::F32)
240 | (F::F64(_), K::F64)
241 )
242 })
243 }
244
245 pub fn to_xyz<T>(&self) -> Option<[T; 3]>
246 where
247 T: Value + NumCast,
248 {
249 use Field as F;
250
251 if self.0.first()?.kind() != T::KIND {
252 return None;
253 }
254
255 Some(match &*self.0 {
256 [F::I8(xv), F::I8(yv), F::I8(zv), ..] => match (&**xv, &**yv, &**zv) {
257 (&[x], &[y], &[z]) => [T::from(x)?, T::from(y)?, T::from(z)?],
258 _ => return None,
259 },
260 [F::I16(xv), F::I16(yv), F::I16(zv), ..] => match (&**xv, &**yv, &**zv) {
261 (&[x], &[y], &[z]) => [T::from(x)?, T::from(y)?, T::from(z)?],
262 _ => return None,
263 },
264 [F::I32(xv), F::I32(yv), F::I32(zv), ..] => match (&**xv, &**yv, &**zv) {
265 (&[x], &[y], &[z]) => [T::from(x)?, T::from(y)?, T::from(z)?],
266 _ => return None,
267 },
268 [F::I64(xv), F::I64(yv), F::I64(zv), ..] => match (&**xv, &**yv, &**zv) {
269 (&[x], &[y], &[z]) => [T::from(x)?, T::from(y)?, T::from(z)?],
270 _ => return None,
271 },
272 [F::U8(xv), F::U8(yv), F::U8(zv), ..] => match (&**xv, &**yv, &**zv) {
273 (&[x], &[y], &[z]) => [T::from(x)?, T::from(y)?, T::from(z)?],
274 _ => return None,
275 },
276 [F::U16(xv), F::U16(yv), F::U16(zv), ..] => match (&**xv, &**yv, &**zv) {
277 (&[x], &[y], &[z]) => [T::from(x)?, T::from(y)?, T::from(z)?],
278 _ => return None,
279 },
280 [F::U32(xv), F::U32(yv), F::U32(zv), ..] => match (&**xv, &**yv, &**zv) {
281 (&[x], &[y], &[z]) => [T::from(x)?, T::from(y)?, T::from(z)?],
282 _ => return None,
283 },
284 [F::U64(xv), F::U64(yv), F::U64(zv), ..] => match (&**xv, &**yv, &**zv) {
285 (&[x], &[y], &[z]) => [T::from(x)?, T::from(y)?, T::from(z)?],
286 _ => return None,
287 },
288 [F::F32(xv), F::F32(yv), F::F32(zv), ..] => match (&**xv, &**yv, &**zv) {
289 (&[x], &[y], &[z]) => [T::from(x)?, T::from(y)?, T::from(z)?],
290 _ => return None,
291 },
292 [F::F64(xv), F::F64(yv), F::F64(zv), ..] => match (&**xv, &**yv, &**zv) {
293 (&[x], &[y], &[z]) => [T::from(x)?, T::from(y)?, T::from(z)?],
294 _ => return None,
295 },
296 _ => return None,
297 })
298 }
299}
300
301impl PcdSerialize for DynRecord {
302 fn is_dynamic() -> bool {
303 true
304 }
305
306 fn write_spec() -> Schema {
307 unreachable!();
308 }
309
310 fn write_chunk<Writer>(&self, writer: &mut Writer, spec: &Schema) -> Result<()>
311 where
312 Writer: Write + Seek,
313 {
314 if !self.is_schema_consistent(spec) {
315 return Err(Error::new_writer_schema_mismatch_error(
316 Self::write_spec().fields,
317 spec.fields.to_vec(),
318 ));
319 }
320
321 for field in self.0.iter() {
322 use Field as F;
323
324 match field {
325 F::I8(values) => {
326 values
327 .iter()
328 .map(|val| Ok(writer.write_i8(*val)?))
329 .collect::<Result<Vec<_>>>()?;
330 }
331 F::I16(values) => {
332 values
333 .iter()
334 .map(|val| Ok(writer.write_i16::<LittleEndian>(*val)?))
335 .collect::<Result<Vec<_>>>()?;
336 }
337 F::I32(values) => {
338 values
339 .iter()
340 .map(|val| Ok(writer.write_i32::<LittleEndian>(*val)?))
341 .collect::<Result<Vec<_>>>()?;
342 }
343 F::I64(values) => {
344 values
345 .iter()
346 .map(|val| Ok(writer.write_i64::<LittleEndian>(*val)?))
347 .collect::<Result<Vec<_>>>()?;
348 }
349 F::U8(values) => {
350 values
351 .iter()
352 .map(|val| Ok(writer.write_u8(*val)?))
353 .collect::<Result<Vec<_>>>()?;
354 }
355 F::U16(values) => {
356 values
357 .iter()
358 .map(|val| Ok(writer.write_u16::<LittleEndian>(*val)?))
359 .collect::<Result<Vec<_>>>()?;
360 }
361 F::U32(values) => {
362 values
363 .iter()
364 .map(|val| Ok(writer.write_u32::<LittleEndian>(*val)?))
365 .collect::<Result<Vec<_>>>()?;
366 }
367 F::U64(values) => {
368 values
369 .iter()
370 .map(|val| Ok(writer.write_u64::<LittleEndian>(*val)?))
371 .collect::<Result<Vec<_>>>()?;
372 }
373 F::F32(values) => {
374 values
375 .iter()
376 .map(|val| Ok(writer.write_f32::<LittleEndian>(*val)?))
377 .collect::<Result<Vec<_>>>()?;
378 }
379 F::F64(values) => {
380 values
381 .iter()
382 .map(|val| Ok(writer.write_f64::<LittleEndian>(*val)?))
383 .collect::<Result<Vec<_>>>()?;
384 }
385 }
386 }
387
388 Ok(())
389 }
390
391 fn write_line<Writer>(&self, writer: &mut Writer, spec: &Schema) -> Result<()>
392 where
393 Writer: Write + Seek,
394 {
395 if !self.is_schema_consistent(spec) {
396 return Err(Error::new_writer_schema_mismatch_error(
397 Self::write_spec().fields,
398 spec.fields.to_vec(),
399 ));
400 }
401
402 let mut tokens = vec![];
403
404 for field in self.0.iter() {
405 use Field as F;
406
407 match field {
408 F::I8(values) => {
409 let iter = values.iter().map(|val| val.to_string());
410 tokens.extend(iter);
411 }
412 F::I16(values) => {
413 let iter = values.iter().map(|val| val.to_string());
414 tokens.extend(iter);
415 }
416 F::I32(values) => {
417 let iter = values.iter().map(|val| val.to_string());
418 tokens.extend(iter);
419 }
420 F::I64(values) => {
421 let iter = values.iter().map(|val| val.to_string());
422 tokens.extend(iter);
423 }
424 F::U8(values) => {
425 let iter = values.iter().map(|val| val.to_string());
426 tokens.extend(iter);
427 }
428 F::U16(values) => {
429 let iter = values.iter().map(|val| val.to_string());
430 tokens.extend(iter);
431 }
432 F::U32(values) => {
433 let iter = values.iter().map(|val| val.to_string());
434 tokens.extend(iter);
435 }
436 F::U64(values) => {
437 let iter = values.iter().map(|val| val.to_string());
438 tokens.extend(iter);
439 }
440 F::F32(values) => {
441 let iter = values.iter().map(|val| val.to_string());
442 tokens.extend(iter);
443 }
444 F::F64(values) => {
445 let iter = values.iter().map(|val| val.to_string());
446 tokens.extend(iter);
447 }
448 }
449 }
450
451 writeln!(writer, "{}", tokens.join(" "))?;
452
453 Ok(())
454 }
455}
456
457impl PcdDeserialize for DynRecord {
458 fn is_dynamic() -> bool {
459 true
460 }
461
462 fn read_spec() -> Vec<(Option<String>, ValueKind, Option<usize>)> {
463 unreachable!();
464 }
465
466 fn read_chunk<R: BufRead>(reader: &mut R, field_defs: &Schema) -> Result<Self> {
467 use Field as F;
468 use ValueKind as K;
469
470 let mut fields = Vec::with_capacity(field_defs.len());
471
472 for def in field_defs.iter() {
473 let FieldDef {
474 kind, count, name, ..
475 } = def;
476 let count = *count;
477
478 if name == "_" {
480 let skip_bytes = kind.byte_size() * count as usize;
481 let mut discard = vec![0u8; skip_bytes];
482 reader.read_exact(&mut discard)?;
483 continue;
484 }
485
486 let counter = 0..count;
487
488 let field = match kind {
489 K::I8 => {
490 let values = counter
491 .map(|_| Ok(reader.read_i8()?))
492 .collect::<Result<Vec<_>>>()?;
493 F::I8(values)
494 }
495 K::I16 => {
496 let values = counter
497 .map(|_| Ok(reader.read_i16::<LittleEndian>()?))
498 .collect::<Result<Vec<_>>>()?;
499 F::I16(values)
500 }
501 K::I32 => {
502 let values = counter
503 .map(|_| Ok(reader.read_i32::<LittleEndian>()?))
504 .collect::<Result<Vec<_>>>()?;
505 F::I32(values)
506 }
507 K::I64 => {
508 let values = counter
509 .map(|_| Ok(reader.read_i64::<LittleEndian>()?))
510 .collect::<Result<Vec<_>>>()?;
511 F::I64(values)
512 }
513 K::U8 => {
514 let values = counter
515 .map(|_| Ok(reader.read_u8()?))
516 .collect::<Result<Vec<_>>>()?;
517 F::U8(values)
518 }
519 K::U16 => {
520 let values = counter
521 .map(|_| Ok(reader.read_u16::<LittleEndian>()?))
522 .collect::<Result<Vec<_>>>()?;
523 F::U16(values)
524 }
525 K::U32 => {
526 let values = counter
527 .map(|_| Ok(reader.read_u32::<LittleEndian>()?))
528 .collect::<Result<Vec<_>>>()?;
529 F::U32(values)
530 }
531 K::U64 => {
532 let values = counter
533 .map(|_| Ok(reader.read_u64::<LittleEndian>()?))
534 .collect::<Result<Vec<_>>>()?;
535 F::U64(values)
536 }
537 K::F32 => {
538 let values = counter
539 .map(|_| Ok(reader.read_f32::<LittleEndian>()?))
540 .collect::<Result<Vec<_>>>()?;
541 F::F32(values)
542 }
543 K::F64 => {
544 let values = counter
545 .map(|_| Ok(reader.read_f64::<LittleEndian>()?))
546 .collect::<Result<Vec<_>>>()?;
547 F::F64(values)
548 }
549 };
550
551 fields.push(field);
552 }
553
554 Ok(Self(fields))
555 }
556
557 fn read_line<R: BufRead>(reader: &mut R, field_defs: &Schema) -> Result<Self> {
558 let mut line = String::new();
559 reader.read_line(&mut line)?;
560 let tokens = line.split_ascii_whitespace().collect::<Vec<_>>();
561
562 {
563 let expect = field_defs.iter().map(|def| def.count as usize).sum();
564 if tokens.len() != expect {
565 return Err(Error::new_text_token_mismatch_error(expect, tokens.len()));
566 }
567 }
568
569 let mut tokens_iter = tokens.into_iter();
570
571 let mut fields = Vec::with_capacity(field_defs.len());
572
573 for def in field_defs.iter() {
574 let FieldDef {
575 kind, count, name, ..
576 } = def;
577 let count = *count as usize;
578
579 if name == "_" {
581 for _ in 0..count {
582 tokens_iter.next();
583 }
584 continue;
585 }
586
587 let field = match kind {
588 ValueKind::I8 => {
589 let values: Vec<i8> = (&mut tokens_iter)
590 .map(|token| token.parse())
591 .take(count)
592 .try_collect()?;
593 Field::I8(values)
594 }
595 ValueKind::I16 => {
596 let values: Vec<i16> = (&mut tokens_iter)
597 .map(|token| token.parse())
598 .take(count)
599 .try_collect()?;
600 Field::I16(values)
601 }
602 ValueKind::I32 => {
603 let values: Vec<i32> = (&mut tokens_iter)
604 .map(|token| token.parse())
605 .take(count)
606 .try_collect()?;
607 Field::I32(values)
608 }
609 ValueKind::I64 => {
610 let values: Vec<i64> = (&mut tokens_iter)
611 .map(|token| token.parse())
612 .take(count)
613 .try_collect()?;
614 Field::I64(values)
615 }
616 ValueKind::U8 => {
617 let values: Vec<u8> = (&mut tokens_iter)
618 .map(|token| token.parse())
619 .take(count)
620 .try_collect()?;
621 Field::U8(values)
622 }
623 ValueKind::U16 => {
624 let values: Vec<u16> = (&mut tokens_iter)
625 .map(|token| token.parse())
626 .take(count)
627 .try_collect()?;
628 Field::U16(values)
629 }
630 ValueKind::U32 => {
631 let values: Vec<u32> = (&mut tokens_iter)
632 .map(|token| token.parse())
633 .take(count)
634 .try_collect()?;
635 Field::U32(values)
636 }
637 ValueKind::U64 => {
638 let values: Vec<u64> = (&mut tokens_iter)
639 .map(|token| token.parse())
640 .take(count)
641 .try_collect()?;
642 Field::U64(values)
643 }
644 ValueKind::F32 => {
645 let values: Vec<f32> = (&mut tokens_iter)
646 .map(|token| token.parse())
647 .take(count)
648 .try_collect()?;
649 Field::F32(values)
650 }
651 ValueKind::F64 => {
652 let values: Vec<f64> = (&mut tokens_iter)
653 .map(|token| token.parse())
654 .take(count)
655 .try_collect()?;
656 Field::F64(values)
657 }
658 };
659
660 fields.push(field);
661 }
662
663 Ok(Self(fields))
664 }
665}
666
667impl PcdDeserialize for u8 {
670 fn is_dynamic() -> bool {
671 false
672 }
673
674 fn read_spec() -> Vec<(Option<String>, ValueKind, Option<usize>)> {
675 vec![(None, ValueKind::U8, Some(1))]
676 }
677
678 fn read_chunk<R: BufRead>(reader: &mut R, _field_defs: &Schema) -> Result<Self> {
679 let value = reader.read_u8()?;
680 Ok(value)
681 }
682
683 fn read_line<R: BufRead>(reader: &mut R, _field_defs: &Schema) -> Result<Self> {
684 let mut line = String::new();
685 reader.read_line(&mut line)?;
686 Ok(line.parse()?)
687 }
688}
689
690impl PcdDeserialize for i8 {
691 fn is_dynamic() -> bool {
692 false
693 }
694
695 fn read_spec() -> Vec<(Option<String>, ValueKind, Option<usize>)> {
696 vec![(None, ValueKind::I8, Some(1))]
697 }
698
699 fn read_chunk<R: BufRead>(reader: &mut R, _field_defs: &Schema) -> Result<Self> {
700 let value = reader.read_i8()?;
701 Ok(value)
702 }
703
704 fn read_line<R: BufRead>(reader: &mut R, _field_defs: &Schema) -> Result<Self> {
705 let mut line = String::new();
706 reader.read_line(&mut line)?;
707 Ok(line.parse()?)
708 }
709}
710
711macro_rules! impl_primitive {
712 ($ty:ty, $kind:ident, $read:ident) => {
713 impl PcdDeserialize for $ty {
714 fn is_dynamic() -> bool {
715 false
716 }
717
718 fn read_spec() -> Vec<(Option<String>, ValueKind, Option<usize>)> {
719 vec![(None, ValueKind::$kind, Some(1))]
720 }
721
722 fn read_chunk<R: BufRead>(reader: &mut R, _field_defs: &Schema) -> Result<Self> {
723 let value = reader.$read::<LittleEndian>()?;
724 Ok(value)
725 }
726
727 fn read_line<R: BufRead>(reader: &mut R, _field_defs: &Schema) -> Result<Self> {
728 let mut line = String::new();
729 reader.read_line(&mut line)?;
730 Ok(line.parse()?)
731 }
732 }
733 };
734}
735
736impl_primitive!(u16, U16, read_u16);
737impl_primitive!(u32, U32, read_u32);
738impl_primitive!(u64, U64, read_u64);
739impl_primitive!(i16, I16, read_i16);
740impl_primitive!(i32, I32, read_i32);
741impl_primitive!(i64, I64, read_i64);
742impl_primitive!(f32, F32, read_f32);
743impl_primitive!(f64, F64, read_f64);