pcd_rs/
record.rs

1#![doc = r##"
2Defines serializing and deserializing traits and common record types.
3
4Any object scanned by readers or written by writers must implement
5[PcdDeserialize](crate::record::PcdDeserialize) 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#![doc = r##"
29The derive macro accepts normal structs and tuple structs, but does not accept unit structs.
30
31[PcdDeserialize](crate::record::PcdDeserialize) 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
72/// [PcdDeserialize](crate::record::PcdDeserialize) is analogous to a _point_ returned from a reader.
73///
74/// The trait is not intended to be implemented from scratch. You must
75/// derive the implementation with `#[derive(PcdDeserialize)]`.
76///
77/// When the PCD data is in Ascii mode, the record is represented by a line of literals.
78/// Otherwise if the data is in binary mode, the record is represented by a fixed size chunk.
79pub 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
86/// [PcdSerialize](crate::record::PcdSerialize) is analogous to a _point_ written by a writer.
87///
88/// The trait is not intended to be implemented from scratch. You must
89/// derive the implementation with `#[derive(PcdSerialize)]`.
90///
91/// When the PCD data is in Ascii mode, the record is represented by a line of literals.
92/// Otherwise if the data is in binary mode, the record is represented by a fixed size chunk.
93pub 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// Runtime record types
101
102/// An enum representation of untyped data fields.
103#[derive(Debug, Clone, PartialEq)]
104pub enum Field {
105    I8(Vec<i8>),
106    I16(Vec<i16>),
107    I32(Vec<i32>),
108    U8(Vec<u8>),
109    U16(Vec<u16>),
110    U32(Vec<u32>),
111    F32(Vec<f32>),
112    F64(Vec<f64>),
113}
114
115impl Field {
116    pub fn kind(&self) -> ValueKind {
117        use Field as F;
118        use ValueKind as K;
119
120        match self {
121            F::I8(_) => K::I8,
122            F::I16(_) => K::I16,
123            F::I32(_) => K::I32,
124            F::U8(_) => K::U8,
125            F::U16(_) => K::U16,
126            F::U32(_) => K::U32,
127            F::F32(_) => K::F32,
128            F::F64(_) => K::F64,
129        }
130    }
131
132    pub fn count(&self) -> usize {
133        use Field as F;
134
135        match self {
136            F::I8(values) => values.len(),
137            F::I16(values) => values.len(),
138            F::I32(values) => values.len(),
139            F::U8(values) => values.len(),
140            F::U16(values) => values.len(),
141            F::U32(values) => values.len(),
142            F::F32(values) => values.len(),
143            F::F64(values) => values.len(),
144        }
145    }
146
147    pub fn to_value<T>(&self) -> Option<T>
148    where
149        T: Value + NumCast,
150    {
151        use Field as F;
152
153        if T::KIND != self.kind() {
154            return None;
155        }
156
157        Some(match self {
158            F::I8(v) => match &**v {
159                &[t] => T::from(t)?,
160                _ => return None,
161            },
162            F::I16(v) => match &**v {
163                &[t] => T::from(t)?,
164                _ => return None,
165            },
166            F::I32(v) => match &**v {
167                &[t] => T::from(t)?,
168                _ => return None,
169            },
170            F::U8(v) => match &**v {
171                &[t] => T::from(t)?,
172                _ => return None,
173            },
174            F::U16(v) => match &**v {
175                &[t] => T::from(t)?,
176                _ => return None,
177            },
178            F::U32(v) => match &**v {
179                &[t] => T::from(t)?,
180                _ => return None,
181            },
182            F::F32(v) => match &**v {
183                &[t] => T::from(t)?,
184                _ => return None,
185            },
186            F::F64(v) => match &**v {
187                &[t] => T::from(t)?,
188                _ => return None,
189            },
190        })
191    }
192}
193
194/// Represents an untyped _point_ in PCD data.
195#[derive(Debug, Clone, PartialEq)]
196pub struct DynRecord(pub Vec<Field>);
197
198impl DynRecord {
199    pub fn is_schema_consistent(&self, schema: &Schema) -> bool {
200        if self.0.len() != schema.len() {
201            return false;
202        }
203
204        self.0
205            .iter()
206            .zip(schema.iter())
207            .all(|(field, schema_field)| {
208                use Field as F;
209                use ValueKind as K;
210
211                if field.count() != schema_field.count as usize {
212                    return false;
213                }
214
215                matches!(
216                    (field, schema_field.kind),
217                    (F::I8(_), K::I8)
218                        | (F::I16(_), K::I16)
219                        | (F::I32(_), K::I32)
220                        | (F::U8(_), K::U8)
221                        | (F::U16(_), K::U16)
222                        | (F::U32(_), K::U32)
223                        | (F::F32(_), K::F32)
224                        | (F::F64(_), K::F64)
225                )
226            })
227    }
228
229    pub fn to_xyz<T>(&self) -> Option<[T; 3]>
230    where
231        T: Value + NumCast,
232    {
233        use Field as F;
234
235        if self.0.first()?.kind() != T::KIND {
236            return None;
237        }
238
239        Some(match &*self.0 {
240            [F::I8(xv), F::I8(yv), F::I8(zv), ..] => match (&**xv, &**yv, &**zv) {
241                (&[x], &[y], &[z]) => [T::from(x)?, T::from(y)?, T::from(z)?],
242                _ => return None,
243            },
244            [F::I16(xv), F::I16(yv), F::I16(zv), ..] => match (&**xv, &**yv, &**zv) {
245                (&[x], &[y], &[z]) => [T::from(x)?, T::from(y)?, T::from(z)?],
246                _ => return None,
247            },
248            [F::I32(xv), F::I32(yv), F::I32(zv), ..] => match (&**xv, &**yv, &**zv) {
249                (&[x], &[y], &[z]) => [T::from(x)?, T::from(y)?, T::from(z)?],
250                _ => return None,
251            },
252            [F::U8(xv), F::U8(yv), F::U8(zv), ..] => match (&**xv, &**yv, &**zv) {
253                (&[x], &[y], &[z]) => [T::from(x)?, T::from(y)?, T::from(z)?],
254                _ => return None,
255            },
256            [F::U16(xv), F::U16(yv), F::U16(zv), ..] => match (&**xv, &**yv, &**zv) {
257                (&[x], &[y], &[z]) => [T::from(x)?, T::from(y)?, T::from(z)?],
258                _ => return None,
259            },
260            [F::U32(xv), F::U32(yv), F::U32(zv), ..] => match (&**xv, &**yv, &**zv) {
261                (&[x], &[y], &[z]) => [T::from(x)?, T::from(y)?, T::from(z)?],
262                _ => return None,
263            },
264            [F::F32(xv), F::F32(yv), F::F32(zv), ..] => match (&**xv, &**yv, &**zv) {
265                (&[x], &[y], &[z]) => [T::from(x)?, T::from(y)?, T::from(z)?],
266                _ => return None,
267            },
268            [F::F64(xv), F::F64(yv), F::F64(zv), ..] => match (&**xv, &**yv, &**zv) {
269                (&[x], &[y], &[z]) => [T::from(x)?, T::from(y)?, T::from(z)?],
270                _ => return None,
271            },
272            _ => return None,
273        })
274    }
275}
276
277impl PcdSerialize for DynRecord {
278    fn is_dynamic() -> bool {
279        true
280    }
281
282    fn write_spec() -> Schema {
283        unreachable!();
284    }
285
286    fn write_chunk<Writer>(&self, writer: &mut Writer, spec: &Schema) -> Result<()>
287    where
288        Writer: Write + Seek,
289    {
290        if !self.is_schema_consistent(spec) {
291            return Err(Error::new_writer_schema_mismatch_error(
292                Self::write_spec().fields,
293                spec.fields.to_vec(),
294            ));
295        }
296
297        for field in self.0.iter() {
298            use Field as F;
299
300            match field {
301                F::I8(values) => {
302                    values
303                        .iter()
304                        .map(|val| Ok(writer.write_i8(*val)?))
305                        .collect::<Result<Vec<_>>>()?;
306                }
307                F::I16(values) => {
308                    values
309                        .iter()
310                        .map(|val| Ok(writer.write_i16::<LittleEndian>(*val)?))
311                        .collect::<Result<Vec<_>>>()?;
312                }
313                F::I32(values) => {
314                    values
315                        .iter()
316                        .map(|val| Ok(writer.write_i32::<LittleEndian>(*val)?))
317                        .collect::<Result<Vec<_>>>()?;
318                }
319                F::U8(values) => {
320                    values
321                        .iter()
322                        .map(|val| Ok(writer.write_u8(*val)?))
323                        .collect::<Result<Vec<_>>>()?;
324                }
325                F::U16(values) => {
326                    values
327                        .iter()
328                        .map(|val| Ok(writer.write_u16::<LittleEndian>(*val)?))
329                        .collect::<Result<Vec<_>>>()?;
330                }
331                F::U32(values) => {
332                    values
333                        .iter()
334                        .map(|val| Ok(writer.write_u32::<LittleEndian>(*val)?))
335                        .collect::<Result<Vec<_>>>()?;
336                }
337                F::F32(values) => {
338                    values
339                        .iter()
340                        .map(|val| Ok(writer.write_f32::<LittleEndian>(*val)?))
341                        .collect::<Result<Vec<_>>>()?;
342                }
343                F::F64(values) => {
344                    values
345                        .iter()
346                        .map(|val| Ok(writer.write_f64::<LittleEndian>(*val)?))
347                        .collect::<Result<Vec<_>>>()?;
348                }
349            }
350        }
351
352        Ok(())
353    }
354
355    fn write_line<Writer>(&self, writer: &mut Writer, spec: &Schema) -> Result<()>
356    where
357        Writer: Write + Seek,
358    {
359        if !self.is_schema_consistent(spec) {
360            return Err(Error::new_writer_schema_mismatch_error(
361                Self::write_spec().fields,
362                spec.fields.to_vec(),
363            ));
364        }
365
366        let mut tokens = vec![];
367
368        for field in self.0.iter() {
369            use Field as F;
370
371            match field {
372                F::I8(values) => {
373                    let iter = values.iter().map(|val| val.to_string());
374                    tokens.extend(iter);
375                }
376                F::I16(values) => {
377                    let iter = values.iter().map(|val| val.to_string());
378                    tokens.extend(iter);
379                }
380                F::I32(values) => {
381                    let iter = values.iter().map(|val| val.to_string());
382                    tokens.extend(iter);
383                }
384                F::U8(values) => {
385                    let iter = values.iter().map(|val| val.to_string());
386                    tokens.extend(iter);
387                }
388                F::U16(values) => {
389                    let iter = values.iter().map(|val| val.to_string());
390                    tokens.extend(iter);
391                }
392                F::U32(values) => {
393                    let iter = values.iter().map(|val| val.to_string());
394                    tokens.extend(iter);
395                }
396                F::F32(values) => {
397                    let iter = values.iter().map(|val| val.to_string());
398                    tokens.extend(iter);
399                }
400                F::F64(values) => {
401                    let iter = values.iter().map(|val| val.to_string());
402                    tokens.extend(iter);
403                }
404            }
405        }
406
407        writeln!(writer, "{}", tokens.join(" "))?;
408
409        Ok(())
410    }
411}
412
413impl PcdDeserialize for DynRecord {
414    fn is_dynamic() -> bool {
415        true
416    }
417
418    fn read_spec() -> Vec<(Option<String>, ValueKind, Option<usize>)> {
419        unreachable!();
420    }
421
422    fn read_chunk<R: BufRead>(reader: &mut R, field_defs: &Schema) -> Result<Self> {
423        use Field as F;
424        use ValueKind as K;
425
426        let fields = field_defs
427            .iter()
428            .map(|def| {
429                let FieldDef { kind, count, .. } = *def;
430
431                let counter = 0..count;
432
433                let field = match kind {
434                    K::I8 => {
435                        let values = counter
436                            .map(|_| Ok(reader.read_i8()?))
437                            .collect::<Result<Vec<_>>>()?;
438                        F::I8(values)
439                    }
440                    K::I16 => {
441                        let values = counter
442                            .map(|_| Ok(reader.read_i16::<LittleEndian>()?))
443                            .collect::<Result<Vec<_>>>()?;
444                        F::I16(values)
445                    }
446                    K::I32 => {
447                        let values = counter
448                            .map(|_| Ok(reader.read_i32::<LittleEndian>()?))
449                            .collect::<Result<Vec<_>>>()?;
450                        F::I32(values)
451                    }
452                    K::U8 => {
453                        let values = counter
454                            .map(|_| Ok(reader.read_u8()?))
455                            .collect::<Result<Vec<_>>>()?;
456                        F::U8(values)
457                    }
458                    K::U16 => {
459                        let values = counter
460                            .map(|_| Ok(reader.read_u16::<LittleEndian>()?))
461                            .collect::<Result<Vec<_>>>()?;
462                        F::U16(values)
463                    }
464                    K::U32 => {
465                        let values = counter
466                            .map(|_| Ok(reader.read_u32::<LittleEndian>()?))
467                            .collect::<Result<Vec<_>>>()?;
468                        F::U32(values)
469                    }
470                    K::F32 => {
471                        let values = counter
472                            .map(|_| Ok(reader.read_f32::<LittleEndian>()?))
473                            .collect::<Result<Vec<_>>>()?;
474                        F::F32(values)
475                    }
476                    K::F64 => {
477                        let values = counter
478                            .map(|_| Ok(reader.read_f64::<LittleEndian>()?))
479                            .collect::<Result<Vec<_>>>()?;
480                        F::F64(values)
481                    }
482                };
483
484                Ok(field)
485            })
486            .collect::<Result<Vec<_>>>()?;
487        Ok(Self(fields))
488    }
489
490    fn read_line<R: BufRead>(reader: &mut R, field_defs: &Schema) -> Result<Self> {
491        let mut line = String::new();
492        reader.read_line(&mut line)?;
493        let tokens = line.split_ascii_whitespace().collect::<Vec<_>>();
494
495        {
496            let expect = field_defs.iter().map(|def| def.count as usize).sum();
497            if tokens.len() != expect {
498                return Err(Error::new_text_token_mismatch_error(expect, tokens.len()));
499            }
500        }
501
502        let mut tokens_iter = tokens.into_iter();
503
504        let fields: Vec<Field> = field_defs
505            .iter()
506            .map(|def| -> Result<_, Error> {
507                let FieldDef { kind, count, .. } = *def;
508
509                let count = count as usize;
510
511                let field = match kind {
512                    ValueKind::I8 => {
513                        let values: Vec<i8> = (&mut tokens_iter)
514                            .map(|token| token.parse())
515                            .take(count)
516                            .try_collect()?;
517                        Field::I8(values)
518                    }
519                    ValueKind::I16 => {
520                        let values: Vec<i16> = (&mut tokens_iter)
521                            .map(|token| token.parse())
522                            .take(count)
523                            .try_collect()?;
524                        Field::I16(values)
525                    }
526                    ValueKind::I32 => {
527                        let values: Vec<i32> = (&mut tokens_iter)
528                            .map(|token| token.parse())
529                            .take(count)
530                            .try_collect()?;
531                        Field::I32(values)
532                    }
533                    ValueKind::U8 => {
534                        let values: Vec<u8> = (&mut tokens_iter)
535                            .map(|token| token.parse())
536                            .take(count)
537                            .try_collect()?;
538                        Field::U8(values)
539                    }
540                    ValueKind::U16 => {
541                        let values: Vec<u16> = (&mut tokens_iter)
542                            .map(|token| token.parse())
543                            .take(count)
544                            .try_collect()?;
545                        Field::U16(values)
546                    }
547                    ValueKind::U32 => {
548                        let values: Vec<u32> = (&mut tokens_iter)
549                            .map(|token| token.parse())
550                            .take(count)
551                            .try_collect()?;
552                        Field::U32(values)
553                    }
554                    ValueKind::F32 => {
555                        let values: Vec<f32> = (&mut tokens_iter)
556                            .map(|token| token.parse())
557                            .take(count)
558                            .try_collect()?;
559                        Field::F32(values)
560                    }
561                    ValueKind::F64 => {
562                        let values: Vec<f64> = (&mut tokens_iter)
563                            .map(|token| token.parse())
564                            .take(count)
565                            .try_collect()?;
566                        Field::F64(values)
567                    }
568                };
569
570                Ok(field)
571            })
572            .try_collect()?;
573
574        Ok(Self(fields))
575    }
576}
577
578// impl for primitive types
579
580impl PcdDeserialize for u8 {
581    fn is_dynamic() -> bool {
582        false
583    }
584
585    fn read_spec() -> Vec<(Option<String>, ValueKind, Option<usize>)> {
586        vec![(None, ValueKind::U8, Some(1))]
587    }
588
589    fn read_chunk<R: BufRead>(reader: &mut R, _field_defs: &Schema) -> Result<Self> {
590        let value = reader.read_u8()?;
591        Ok(value)
592    }
593
594    fn read_line<R: BufRead>(reader: &mut R, _field_defs: &Schema) -> Result<Self> {
595        let mut line = String::new();
596        reader.read_line(&mut line)?;
597        Ok(line.parse()?)
598    }
599}
600
601impl PcdDeserialize for i8 {
602    fn is_dynamic() -> bool {
603        false
604    }
605
606    fn read_spec() -> Vec<(Option<String>, ValueKind, Option<usize>)> {
607        vec![(None, ValueKind::I8, Some(1))]
608    }
609
610    fn read_chunk<R: BufRead>(reader: &mut R, _field_defs: &Schema) -> Result<Self> {
611        let value = reader.read_i8()?;
612        Ok(value)
613    }
614
615    fn read_line<R: BufRead>(reader: &mut R, _field_defs: &Schema) -> Result<Self> {
616        let mut line = String::new();
617        reader.read_line(&mut line)?;
618        Ok(line.parse()?)
619    }
620}
621
622macro_rules! impl_primitive {
623    ($ty:ty, $kind:ident, $read:ident) => {
624        impl PcdDeserialize for $ty {
625            fn is_dynamic() -> bool {
626                false
627            }
628
629            fn read_spec() -> Vec<(Option<String>, ValueKind, Option<usize>)> {
630                vec![(None, ValueKind::$kind, Some(1))]
631            }
632
633            fn read_chunk<R: BufRead>(reader: &mut R, _field_defs: &Schema) -> Result<Self> {
634                let value = reader.$read::<LittleEndian>()?;
635                Ok(value)
636            }
637
638            fn read_line<R: BufRead>(reader: &mut R, _field_defs: &Schema) -> Result<Self> {
639                let mut line = String::new();
640                reader.read_line(&mut line)?;
641                Ok(line.parse()?)
642            }
643        }
644    };
645}
646
647impl_primitive!(u16, U16, read_u16);
648impl_primitive!(u32, U32, read_u32);
649impl_primitive!(i16, I16, read_i16);
650impl_primitive!(i32, I32, read_i32);
651impl_primitive!(f32, F32, read_f32);
652impl_primitive!(f64, F64, read_f64);