1use crate::Result;
4use std::{
5 fs::File,
6 io::{BufRead, BufReader},
7 iter::FromIterator,
8 ops::Index,
9 path::Path,
10};
11
12#[derive(Debug, Clone, PartialEq)]
14pub struct PcdMeta {
15 pub version: String,
16 pub width: u64,
17 pub height: u64,
18 pub viewpoint: ViewPoint,
19 pub num_points: u64,
20 pub data: DataKind,
21 pub field_defs: Schema,
22}
23
24impl PcdMeta {
25 pub fn from_path(path: impl AsRef<Path>) -> Result<Self> {
27 let file = BufReader::new(File::open(path.as_ref())?);
28 Self::from_reader(file)
29 }
30
31 pub fn from_reader(mut reader: impl BufRead) -> Result<Self> {
33 let mut line_count = 0;
34 crate::utils::load_meta(&mut reader, &mut line_count)
35 }
36}
37
38#[derive(Debug, Clone, PartialEq)]
40pub struct ViewPoint {
41 pub tx: f64,
42 pub ty: f64,
43 pub tz: f64,
44 pub qw: f64,
45 pub qx: f64,
46 pub qy: f64,
47 pub qz: f64,
48}
49
50impl Default for ViewPoint {
51 fn default() -> Self {
52 ViewPoint {
53 tx: 0.0,
54 ty: 0.0,
55 tz: 0.0,
56 qw: 1.0,
57 qx: 0.0,
58 qy: 0.0,
59 qz: 0.0,
60 }
61 }
62}
63
64#[derive(Debug, Clone, Copy, PartialEq, Eq)]
66pub enum DataKind {
67 Ascii,
68 Binary,
69 BinaryCompressed,
70}
71
72#[derive(Debug, Clone, Copy, PartialEq, Eq)]
74pub enum TypeKind {
75 I,
76 U,
77 F,
78}
79
80#[derive(Debug, Clone, Copy, PartialEq, Eq)]
82pub enum ValueKind {
83 U8,
84 U16,
85 U32,
86 U64,
87 I8,
88 I16,
89 I32,
90 I64,
91 F32,
92 F64,
93}
94
95impl ValueKind {
96 pub fn byte_size(&self) -> usize {
98 match self {
99 ValueKind::U8 | ValueKind::I8 => 1,
100 ValueKind::U16 | ValueKind::I16 => 2,
101 ValueKind::U32 | ValueKind::I32 | ValueKind::F32 => 4,
102 ValueKind::U64 | ValueKind::I64 | ValueKind::F64 => 8,
103 }
104 }
105}
106
107#[derive(Debug, Clone, PartialEq, Eq)]
109pub struct FieldDef {
110 pub name: String,
111 pub kind: ValueKind,
112 pub count: u64,
113}
114
115impl FieldDef {
116 pub fn is_padding(&self) -> bool {
118 self.name == "_"
119 }
120}
121
122#[derive(Debug, Clone, PartialEq, Eq)]
124pub struct Schema {
125 pub fields: Vec<FieldDef>,
126}
127
128impl Schema {
129 pub fn is_empty(&self) -> bool {
130 self.fields.is_empty()
131 }
132
133 pub fn len(&self) -> usize {
134 self.fields.len()
135 }
136
137 pub fn iter(&self) -> std::slice::Iter<'_, FieldDef> {
138 self.into_iter()
139 }
140}
141
142impl Index<usize> for Schema {
143 type Output = FieldDef;
144
145 fn index(&self, index: usize) -> &Self::Output {
146 self.fields.index(index)
147 }
148}
149
150impl IntoIterator for Schema {
151 type Item = FieldDef;
152 type IntoIter = std::vec::IntoIter<FieldDef>;
153
154 fn into_iter(self) -> Self::IntoIter {
155 self.fields.into_iter()
156 }
157}
158
159impl<'a> IntoIterator for &'a Schema {
160 type Item = &'a FieldDef;
161 type IntoIter = std::slice::Iter<'a, FieldDef>;
162
163 fn into_iter(self) -> Self::IntoIter {
164 self.fields.iter()
165 }
166}
167
168impl FromIterator<(String, ValueKind, u64)> for Schema {
169 fn from_iter<T: IntoIterator<Item = (String, ValueKind, u64)>>(iter: T) -> Self {
170 let fields = iter
171 .into_iter()
172 .map(|(name, kind, count)| FieldDef { name, kind, count })
173 .collect();
174 Self { fields }
175 }
176}
177
178impl<'a> FromIterator<(&'a str, ValueKind, u64)> for Schema {
179 fn from_iter<T: IntoIterator<Item = (&'a str, ValueKind, u64)>>(iter: T) -> Self {
180 iter.into_iter()
181 .map(|(name, kind, count)| (name.to_string(), kind, count))
182 .collect()
183 }
184}
185
186impl FromIterator<FieldDef> for Schema {
187 fn from_iter<T: IntoIterator<Item = FieldDef>>(iter: T) -> Self {
188 Self {
189 fields: iter.into_iter().collect(),
190 }
191 }
192}
193
194impl<'a> FromIterator<&'a FieldDef> for Schema {
195 fn from_iter<T: IntoIterator<Item = &'a FieldDef>>(iter: T) -> Self {
196 Self {
197 fields: iter.into_iter().map(|field| field.to_owned()).collect(),
198 }
199 }
200}