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}