pointrain_io/
field.rs

1use bytes::Buf;
2use pointrain_core::types::{Float, Rgb};
3
4use crate::error::ParseNumberError;
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7pub(crate) enum PointFieldType {
8    U8,
9    U16,
10    U32,
11    I8,
12    I16,
13    I32,
14    F32,
15    F64,
16}
17
18impl PointFieldType {
19    pub fn from_pcd_type_and_size(r#type: char, size: u8) -> Result<Self, String> {
20        Ok(match (r#type, size) {
21            ('U', 1) => Self::U8,
22            ('U', 2) => Self::U16,
23            ('U', 4) => Self::U32,
24            ('I', 1) => Self::I8,
25            ('I', 2) => Self::I16,
26            ('I', 4) => Self::I32,
27            ('F', 4) => Self::F32,
28            ('F', 8) => Self::F64,
29            _ => {
30                return Err(format!(
31                    "Invalid pair of type and size: {} (type) {} (size)",
32                    r#type, size
33                ));
34            }
35        })
36    }
37
38    pub fn from_ply_type(r#type: &str) -> Result<Self, String> {
39        Ok(match r#type {
40            "char" => Self::I8,
41            "uchar" => Self::U8,
42            "short" => Self::I16,
43            "ushort" => Self::U16,
44            "int" => Self::I32,
45            "uint" => Self::U32,
46            "float" => Self::F32,
47            "double" => Self::F64,
48            _ => {
49                return Err(format!("Unknown point field type: {}", r#type));
50            }
51        })
52    }
53
54    fn bytes(self) -> usize {
55        match self {
56            Self::U8 => 1,
57            Self::U16 => 2,
58            Self::U32 => 4,
59            Self::I8 => 1,
60            Self::I16 => 2,
61            Self::I32 => 4,
62            Self::F32 => 4,
63            Self::F64 => 8,
64        }
65    }
66}
67
68#[derive(Debug, Clone)]
69pub struct PointField {
70    pub(crate) name: String,
71    pub(crate) datatype: PointFieldType,
72    pub(crate) count: usize,
73}
74
75impl PointField {
76    pub(crate) fn bytes(&self) -> usize {
77        self.count * self.datatype.bytes()
78    }
79}
80
81#[derive(Debug, Clone, Copy)]
82pub enum PointFieldDatum {
83    U8(u8),
84    U16(u16),
85    U32(u32),
86    I8(i8),
87    I16(i16),
88    I32(i32),
89    F32(f32),
90    F64(f64),
91}
92
93impl PointFieldDatum {
94    pub(crate) fn parse(s: &str, r#type: PointFieldType) -> Result<Self, ParseNumberError> {
95        use PointFieldType::*;
96
97        Ok(match r#type {
98            U8 => Self::U8(s.parse()?),
99            U16 => Self::U16(s.parse()?),
100            U32 => Self::U32(s.parse()?),
101            I8 => Self::I8(s.parse()?),
102            I16 => Self::I16(s.parse()?),
103            I32 => Self::I32(s.parse()?),
104            F32 => Self::F32(s.parse()?),
105            F64 => Self::F64(s.parse()?),
106        })
107    }
108
109    pub(crate) fn from_bytes_le(bytes: &mut &[u8], r#type: PointFieldType) -> Self {
110        use PointFieldType::*;
111
112        match r#type {
113            U8 => Self::U8(bytes.get_u8()),
114            U16 => Self::U16(bytes.get_u16_le()),
115            U32 => Self::U32(bytes.get_u32_le()),
116            I8 => Self::I8(bytes.get_i8()),
117            I16 => Self::I16(bytes.get_i16_le()),
118            I32 => Self::I32(bytes.get_i32_le()),
119            F32 => Self::F32(bytes.get_f32_le()),
120            F64 => Self::F64(bytes.get_f64_le()),
121        }
122    }
123
124    pub(crate) fn from_bytes_be(bytes: &mut &[u8], r#type: PointFieldType) -> Self {
125        use PointFieldType::*;
126
127        match r#type {
128            U8 => Self::U8(bytes.get_u8()),
129            U16 => Self::U16(bytes.get_u16()),
130            U32 => Self::U32(bytes.get_u32()),
131            I8 => Self::I8(bytes.get_i8()),
132            I16 => Self::I16(bytes.get_i16()),
133            I32 => Self::I32(bytes.get_i32()),
134            F32 => Self::F32(bytes.get_f32()),
135            F64 => Self::F64(bytes.get_f64()),
136        }
137    }
138
139    pub(crate) fn to_float(self) -> Float {
140        match self {
141            Self::U8(v) => v.into(),
142            Self::U16(v) => v.into(),
143            Self::U32(v) => f64::from(v) as f32,
144            Self::I8(v) => v.into(),
145            Self::I16(v) => v.into(),
146            Self::I32(v) => f64::from(v) as f32,
147            Self::F32(v) => v,
148            Self::F64(v) => v as f32,
149        }
150    }
151
152    pub(crate) fn as_u8(self) -> Result<u8, String> {
153        match self {
154            Self::U8(v) => Ok(v),
155            _ => Err(format!("{:?} cannot be parsed as u8", self)),
156        }
157    }
158
159    pub(crate) fn to_color(self) -> Result<Rgb, String> {
160        Ok(match self {
161            Self::F32(v) => {
162                let bytes = v.to_le_bytes();
163                Rgb::new(bytes[0], bytes[1], bytes[2])
164            }
165            _ => return Err(format!("{:?} cannot be parsed as RGB", self)),
166        })
167    }
168}