use crate::Result;
use std::{
fs::File,
io::{BufRead, BufReader},
iter::FromIterator,
ops::Index,
path::Path,
};
#[derive(Debug, Clone, PartialEq)]
pub struct PcdMeta {
pub version: String,
pub width: u64,
pub height: u64,
pub viewpoint: ViewPoint,
pub num_points: u64,
pub data: DataKind,
pub field_defs: Schema,
}
impl PcdMeta {
pub fn from_path(path: impl AsRef<Path>) -> Result<Self> {
let file = BufReader::new(File::open(path.as_ref())?);
Self::from_reader(file)
}
pub fn from_reader(mut reader: impl BufRead) -> Result<Self> {
let mut line_count = 0;
crate::utils::load_meta(&mut reader, &mut line_count)
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct ViewPoint {
pub tx: f64,
pub ty: f64,
pub tz: f64,
pub qw: f64,
pub qx: f64,
pub qy: f64,
pub qz: f64,
}
impl Default for ViewPoint {
fn default() -> Self {
ViewPoint {
tx: 0.0,
ty: 0.0,
tz: 0.0,
qw: 1.0,
qx: 0.0,
qy: 0.0,
qz: 0.0,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DataKind {
Ascii,
Binary,
BinaryCompressed,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TypeKind {
I,
U,
F,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ValueKind {
U8,
U16,
U32,
U64,
I8,
I16,
I32,
I64,
F32,
F64,
}
impl ValueKind {
pub fn byte_size(&self) -> usize {
match self {
ValueKind::U8 | ValueKind::I8 => 1,
ValueKind::U16 | ValueKind::I16 => 2,
ValueKind::U32 | ValueKind::I32 | ValueKind::F32 => 4,
ValueKind::U64 | ValueKind::I64 | ValueKind::F64 => 8,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct FieldDef {
pub name: String,
pub kind: ValueKind,
pub count: u64,
}
impl FieldDef {
pub fn is_padding(&self) -> bool {
self.name == "_"
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Schema {
pub fields: Vec<FieldDef>,
}
impl Schema {
pub fn is_empty(&self) -> bool {
self.fields.is_empty()
}
pub fn len(&self) -> usize {
self.fields.len()
}
pub fn iter(&self) -> std::slice::Iter<'_, FieldDef> {
self.into_iter()
}
}
impl Index<usize> for Schema {
type Output = FieldDef;
fn index(&self, index: usize) -> &Self::Output {
self.fields.index(index)
}
}
impl IntoIterator for Schema {
type Item = FieldDef;
type IntoIter = std::vec::IntoIter<FieldDef>;
fn into_iter(self) -> Self::IntoIter {
self.fields.into_iter()
}
}
impl<'a> IntoIterator for &'a Schema {
type Item = &'a FieldDef;
type IntoIter = std::slice::Iter<'a, FieldDef>;
fn into_iter(self) -> Self::IntoIter {
self.fields.iter()
}
}
impl FromIterator<(String, ValueKind, u64)> for Schema {
fn from_iter<T: IntoIterator<Item = (String, ValueKind, u64)>>(iter: T) -> Self {
let fields = iter
.into_iter()
.map(|(name, kind, count)| FieldDef { name, kind, count })
.collect();
Self { fields }
}
}
impl<'a> FromIterator<(&'a str, ValueKind, u64)> for Schema {
fn from_iter<T: IntoIterator<Item = (&'a str, ValueKind, u64)>>(iter: T) -> Self {
iter.into_iter()
.map(|(name, kind, count)| (name.to_string(), kind, count))
.collect()
}
}
impl FromIterator<FieldDef> for Schema {
fn from_iter<T: IntoIterator<Item = FieldDef>>(iter: T) -> Self {
Self {
fields: iter.into_iter().collect(),
}
}
}
impl<'a> FromIterator<&'a FieldDef> for Schema {
fn from_iter<T: IntoIterator<Item = &'a FieldDef>>(iter: T) -> Self {
Self {
fields: iter.into_iter().map(|field| field.to_owned()).collect(),
}
}
}