1use lazy_static::lazy_static;
17use nalgebra::Vector3;
18use num_traits::AsPrimitive;
19use std::{collections::HashMap, ops::Range};
20
21use crate::layout::{PointAttributeDataType, PointAttributeDefinition, PointLayout};
22
23struct RawAttributeConverter {
26 conversion_fn: AttributeConversionFn,
27 source_range: Range<usize>,
28 target_range: Range<usize>,
29}
30
31impl RawAttributeConverter {
32 pub fn new(
33 conversion_fn: AttributeConversionFn,
34 source_offset: u64,
35 source_size: u64,
36 target_offset: u64,
37 target_size: u64,
38 ) -> Self {
39 Self {
40 conversion_fn,
41 source_range: Range {
42 start: source_offset as usize,
43 end: (source_offset + source_size) as usize,
44 },
45 target_range: Range {
46 start: target_offset as usize,
47 end: (target_offset + target_size) as usize,
48 },
49 }
50 }
51
52 unsafe fn convert(&self, source_point: &[u8], target_point: &mut [u8]) {
54 let source_slice = &source_point[self.source_range.clone()];
55 let target_slice = &mut target_point[self.target_range.clone()];
56
57 (self.conversion_fn)(source_slice, target_slice);
58 }
59}
60
61pub struct RawPointConverter {
63 attribute_converters: Vec<RawAttributeConverter>,
64}
65
66impl RawPointConverter {
67 pub fn from_to(from_layout: &PointLayout, to_layout: &PointLayout) -> RawPointConverter {
70 let converters = from_layout
71 .attributes()
72 .filter(|&from_attribute| to_layout.has_attribute_with_name(from_attribute.name()))
73 .filter_map(|from_attribute| {
74 let to_attribute = to_layout
75 .get_attribute_by_name(from_attribute.name())
76 .unwrap();
77 let conversion_fn = get_converter_for_attributes(
78 from_attribute.attribute_definition(),
79 to_attribute.attribute_definition(),
80 );
81 conversion_fn.map(|conversion_fn| {
82 RawAttributeConverter::new(
83 conversion_fn,
84 from_attribute.offset(),
85 from_attribute.size(),
86 to_attribute.offset(),
87 to_attribute.size(),
88 )
89 })
90 })
91 .collect::<Vec<_>>();
92
93 Self {
94 attribute_converters: converters,
95 }
96 }
97
98 pub unsafe fn convert(&self, source_point: &[u8], target_point: &mut [u8]) {
105 for converter in self.attribute_converters.iter() {
106 converter.convert(source_point, target_point);
107 }
108 }
109}
110
111pub type AttributeConversionFn = unsafe fn(&[u8], &mut [u8]) -> ();
113
114pub fn get_converter_for_attributes(
123 from_attribute: &PointAttributeDefinition,
124 to_attribute: &PointAttributeDefinition,
125) -> Option<AttributeConversionFn> {
126 assert_eq!(from_attribute.name(), to_attribute.name());
127 if from_attribute.datatype() == to_attribute.datatype() {
128 return None;
129 }
130
131 get_generic_converter(from_attribute.datatype(), to_attribute.datatype())
132}
133
134macro_rules! insert_scalar_converter_using_as {
135 ($prim_from:ident, $prim_to:ident, $type_from:ident, $type_to:ident, $map:expr) => {
136 assert!(($map)
138 .insert(
139 (
140 PointAttributeDataType::$type_from,
141 PointAttributeDataType::$type_to,
142 ),
143 convert_scalar_using_as::<$prim_from, $prim_to>,
144 )
145 .is_none());
146 assert!(($map)
147 .insert(
148 (
149 PointAttributeDataType::$type_to,
150 PointAttributeDataType::$type_from,
151 ),
152 convert_scalar_using_as::<$prim_to, $prim_from>,
153 )
154 .is_none());
155 };
156}
157
158macro_rules! insert_vec3_converter_using_as {
159 ($prim_from:ident, $prim_to:ident, $type_from:ident, $type_to:ident, $map:expr) => {
160 assert!(($map)
162 .insert(
163 (
164 PointAttributeDataType::$type_from,
165 PointAttributeDataType::$type_to,
166 ),
167 convert_vec3_using_as::<$prim_from, $prim_to>,
168 )
169 .is_none());
170 assert!(($map)
171 .insert(
172 (
173 PointAttributeDataType::$type_to,
174 PointAttributeDataType::$type_from,
175 ),
176 convert_vec3_using_as::<$prim_to, $prim_from>,
177 )
178 .is_none());
179 };
180}
181
182pub fn get_generic_converter(
185 from_type: PointAttributeDataType,
186 to_type: PointAttributeDataType,
187) -> Option<AttributeConversionFn> {
188 lazy_static! {
189 static ref GENERIC_CONVERTERS: HashMap<(PointAttributeDataType, PointAttributeDataType), AttributeConversionFn> = {
190 let mut converters = HashMap::<
191 (PointAttributeDataType, PointAttributeDataType),
192 AttributeConversionFn,
193 >::new();
194 insert_scalar_converter_using_as!(u8, u16, U8, U16, converters);
195 insert_scalar_converter_using_as!(u8, u32, U8, U32, converters);
196 insert_scalar_converter_using_as!(u8, u64, U8, U64, converters);
197 insert_scalar_converter_using_as!(u8, i8, U8, I8, converters);
198 insert_scalar_converter_using_as!(u8, i16, U8, I16, converters);
199 insert_scalar_converter_using_as!(u8, i32, U8, I32, converters);
200 insert_scalar_converter_using_as!(u8, i64, U8, I64, converters);
201 insert_scalar_converter_using_as!(u8, f32, U8, F32, converters);
202 insert_scalar_converter_using_as!(u8, f64, U8, F64, converters);
203
204 insert_scalar_converter_using_as!(u16, u32, U16, U32, converters);
205 insert_scalar_converter_using_as!(u16, u64, U16, U64, converters);
206 insert_scalar_converter_using_as!(u16, i8, U16, I8, converters);
207 insert_scalar_converter_using_as!(u16, i16, U16, I16, converters);
208 insert_scalar_converter_using_as!(u16, i32, U16, I32, converters);
209 insert_scalar_converter_using_as!(u16, i64, U16, I64, converters);
210 insert_scalar_converter_using_as!(u16, f32, U16, F32, converters);
211 insert_scalar_converter_using_as!(u16, f64, U16, F64, converters);
212
213 insert_scalar_converter_using_as!(u32, u64, U32, U64, converters);
214 insert_scalar_converter_using_as!(u32, i8, U32, I8, converters);
215 insert_scalar_converter_using_as!(u32, i16, U32, I16, converters);
216 insert_scalar_converter_using_as!(u32, i32, U32, I32, converters);
217 insert_scalar_converter_using_as!(u32, i64, U32, I64, converters);
218 insert_scalar_converter_using_as!(u32, f32, U32, F32, converters);
219 insert_scalar_converter_using_as!(u32, f64, U32, F64, converters);
220
221 insert_scalar_converter_using_as!(u64, i8, U64, I8, converters);
222 insert_scalar_converter_using_as!(u64, i16, U64, I16, converters);
223 insert_scalar_converter_using_as!(u64, i32, U64, I32, converters);
224 insert_scalar_converter_using_as!(u64, i64, U64, I64, converters);
225 insert_scalar_converter_using_as!(u64, f32, U64, F32, converters);
226 insert_scalar_converter_using_as!(u64, f64, U64, F64, converters);
227
228 insert_scalar_converter_using_as!(i8, i16, I8, I16, converters);
229 insert_scalar_converter_using_as!(i8, i32, I8, I32, converters);
230 insert_scalar_converter_using_as!(i8, i64, I8, I64, converters);
231 insert_scalar_converter_using_as!(i8, f32, I8, F32, converters);
232 insert_scalar_converter_using_as!(i8, f64, I8, F64, converters);
233
234 insert_scalar_converter_using_as!(i16, i32, I16, I32, converters);
235 insert_scalar_converter_using_as!(i16, i64, I16, I64, converters);
236 insert_scalar_converter_using_as!(i16, f32, I16, F32, converters);
237 insert_scalar_converter_using_as!(i16, f64, I16, F64, converters);
238
239 insert_scalar_converter_using_as!(i32, i64, I32, I64, converters);
240 insert_scalar_converter_using_as!(i32, f32, I32, F32, converters);
241 insert_scalar_converter_using_as!(i32, f64, I32, F64, converters);
242
243 insert_scalar_converter_using_as!(i64, f32, I64, F32, converters);
244 insert_scalar_converter_using_as!(i64, f64, I64, F64, converters);
245
246 insert_scalar_converter_using_as!(f32, f64, F32, F64, converters);
247
248 insert_vec3_converter_using_as!(f32, f64, Vec3f32, Vec3f64, converters);
249
250 insert_vec3_converter_using_as!(u8, u16, Vec3u8, Vec3u16, converters);
251 insert_vec3_converter_using_as!(u8, i32, Vec3u8, Vec3i32, converters);
252 insert_vec3_converter_using_as!(u8, f32, Vec3u8, Vec3f32, converters);
253 insert_vec3_converter_using_as!(u8, f64, Vec3u8, Vec3f64, converters);
254
255 insert_vec3_converter_using_as!(u16, i32, Vec3u16, Vec3i32, converters);
256 insert_vec3_converter_using_as!(u16, f32, Vec3u16, Vec3f32, converters);
257 insert_vec3_converter_using_as!(u16, f64, Vec3u16, Vec3f64, converters);
258
259 insert_vec3_converter_using_as!(i32, f32, Vec3i32, Vec3f32, converters);
260 insert_vec3_converter_using_as!(i32, f64, Vec3i32, Vec3f64, converters);
261
262 converters
263 };
264 }
265
266 let key = (from_type, to_type);
267 let f = GENERIC_CONVERTERS
268 .get(&key)
269 .unwrap_or_else(|| panic!("Invalid conversion {} -> {}", from_type, to_type));
270 Some(*f)
271}
272
273pub unsafe fn convert_unit(from: &[u8], to: &mut [u8]) {
298 to.copy_from_slice(from)
299}
300
301unsafe fn convert_scalar_using_as<From, To>(from: &[u8], to: &mut [u8])
311where
312 From: AsPrimitive<To> + Copy,
313 To: Copy + 'static,
314{
315 let from_ptr = from.as_ptr() as *const From;
316 let to_ptr = to.as_mut_ptr() as *mut To;
317
318 let from_value = from_ptr.read_unaligned();
319 let to_value = from_value.as_();
320 to_ptr.write_unaligned(to_value);
321}
322
323unsafe fn convert_vec3_using_as<From, To>(from: &[u8], to: &mut [u8])
333where
334 From: AsPrimitive<To> + Copy,
335 To: Copy + 'static,
336{
337 let from_ptr = from.as_ptr() as *const Vector3<From>;
338 let to_ptr = to.as_mut_ptr() as *mut Vector3<To>;
339
340 let from_vec = from_ptr.read_unaligned();
341 let to_vec = Vector3::<To>::new(from_vec[0].as_(), from_vec[1].as_(), from_vec[2].as_());
342 to_ptr.write_unaligned(to_vec);
343}