rs_pcd/header/
mod.rs

1// Copyright 2025 bigpear0201
2
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6
7//     http://www.apache.org/licenses/LICENSE-2.0
8
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use crate::error::{PcdError, Result};
16use std::str::FromStr;
17
18mod parser;
19mod builder;
20pub use parser::parse_header;
21pub use builder::PcdHeaderBuilder;
22
23#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
24pub enum DataFormat {
25    #[default]
26    Ascii,
27    Binary,
28    BinaryCompressed,
29}
30
31impl FromStr for DataFormat {
32    type Err = PcdError;
33
34    fn from_str(s: &str) -> Result<Self> {
35        match s {
36            "ascii" => Ok(DataFormat::Ascii),
37            "binary" => Ok(DataFormat::Binary),
38            "binary_compressed" => Ok(DataFormat::BinaryCompressed),
39            _ => Err(PcdError::UnsupportedDataFormat(s.to_string())),
40        }
41    }
42}
43
44#[derive(Debug, Clone, Copy, PartialEq, Eq)]
45pub enum ValueType {
46    U8,
47    U16,
48    U32,
49    I8,
50    I16,
51    I32,
52    F32,
53    F64,
54}
55
56impl ValueType {
57    pub fn size(&self) -> usize {
58        match self {
59            ValueType::U8 | ValueType::I8 => 1,
60            ValueType::U16 | ValueType::I16 => 2,
61            ValueType::U32 | ValueType::I32 | ValueType::F32 => 4,
62            ValueType::F64 => 8,
63        }
64    }
65}
66
67#[derive(Debug, Clone, Default)]
68pub struct PcdHeader {
69    pub version: String,
70    pub fields: Vec<String>,
71    pub sizes: Vec<usize>,
72    pub types: Vec<char>,
73    pub counts: Vec<usize>,
74    pub width: u32,
75    pub height: u32,
76    pub viewpoint: [f64; 7],
77    pub points: usize,
78    pub data: DataFormat,
79}
80
81impl PcdHeader {
82    pub fn is_organized(&self) -> bool {
83        self.height > 1
84    }
85
86    pub fn point_step(&self) -> usize {
87        self.sizes.iter().sum() // Simplified; actual stride might handle padding if counts > 1? Standard PCD usually tightly packed?
88        // Actually, PCD spec says "SIZE is the size of each dimension in bytes".
89        // "COUNT is the number of elements in each dimension."
90        // Point step is usually sum(size * count).
91    }
92
93    pub fn total_point_step(&self) -> usize {
94        self.sizes
95            .iter()
96            .zip(self.counts.iter())
97            .map(|(size, count)| size * count)
98            .sum()
99    }
100}