1use crate::error::SpatialError;
2use crate::types::*;
3use bytes::Buf;
4
5pub fn decode_spatial(buf: &mut &[u8]) -> Result<SpatialValue, SpatialError> {
6 if buf.remaining() < 1 {
7 return Err(SpatialError::DecodeError(
8 "Insufficient data for SpatialType".into(),
9 ));
10 }
11
12 let type_id = buf.get_u8();
13
14 match type_id {
15 0x01 => {
16 if buf.remaining() < 8 {
18 return Err(SpatialError::DecodeError(
19 "Insufficient data for Position2D".into(),
20 ));
21 }
22 let x = buf.get_f32();
23 let y = buf.get_f32();
24 Ok(SpatialValue::S1(Position2D { x, y }))
25 }
26 0x02 => {
27 if buf.remaining() < 12 {
29 return Err(SpatialError::DecodeError(
30 "Insufficient data for Position3D".into(),
31 ));
32 }
33 let x = buf.get_f32();
34 let y = buf.get_f32();
35 let z = buf.get_f32();
36 Ok(SpatialValue::S2(Position3D { x, y, z }))
37 }
38 0x03 => {
39 if buf.remaining() < 12 {
41 return Err(SpatialError::DecodeError(
42 "Insufficient data for Rotation".into(),
43 ));
44 }
45 let pitch = buf.get_f32();
46 let yaw = buf.get_f32();
47 let roll = buf.get_f32();
48 Ok(SpatialValue::S3(Rotation { pitch, yaw, roll }))
49 }
50 0x04 => {
51 if buf.remaining() < 12 {
53 return Err(SpatialError::DecodeError(
54 "Insufficient data for Velocity".into(),
55 ));
56 }
57 let vx = buf.get_f32();
58 let vy = buf.get_f32();
59 let vz = buf.get_f32();
60 Ok(SpatialValue::S4(Velocity { vx, vy, vz }))
61 }
62 0x05 => {
63 if buf.remaining() < 12 {
65 return Err(SpatialError::DecodeError(
66 "Insufficient data for Acceleration".into(),
67 ));
68 }
69 let ax = buf.get_f32();
70 let ay = buf.get_f32();
71 let az = buf.get_f32();
72 Ok(SpatialValue::S5(Acceleration { ax, ay, az }))
73 }
74 0x06 => {
75 if buf.remaining() < 24 {
77 return Err(SpatialError::DecodeError(
78 "Insufficient data for BoundingBox".into(),
79 ));
80 }
81 let min_x = buf.get_f32();
82 let min_y = buf.get_f32();
83 let min_z = buf.get_f32();
84 let max_x = buf.get_f32();
85 let max_y = buf.get_f32();
86 let max_z = buf.get_f32();
87 Ok(SpatialValue::S6(BoundingBox {
88 min_x,
89 min_y,
90 min_z,
91 max_x,
92 max_y,
93 max_z,
94 }))
95 }
96 0x07 => {
97 if buf.remaining() < 16 {
99 return Err(SpatialError::DecodeError(
100 "Insufficient data for Quaternion".into(),
101 ));
102 }
103 let qx = buf.get_f32();
104 let qy = buf.get_f32();
105 let qz = buf.get_f32();
106 let qw = buf.get_f32();
107 Ok(SpatialValue::S7(Quaternion { qx, qy, qz, qw }))
108 }
109 0x08 => {
110 if buf.remaining() < 4 {
112 return Err(SpatialError::DecodeError(
113 "Insufficient data for Path length".into(),
114 ));
115 }
116 let len = buf.get_u32() as usize;
117 if buf.remaining() < len * 12 {
118 return Err(SpatialError::DecodeError(
119 "Insufficient data for Path points".into(),
120 ));
121 }
122 let mut points = Vec::with_capacity(len);
123 for _ in 0..len {
124 let x = buf.get_f32();
125 let y = buf.get_f32();
126 let z = buf.get_f32();
127 points.push(Position3D { x, y, z });
128 }
129 Ok(SpatialValue::S8(Path { points }))
130 }
131 0x09 => {
132 if buf.remaining() < 36 {
134 return Err(SpatialError::DecodeError(
135 "Insufficient data for Transform".into(),
136 ));
137 }
138 let px = buf.get_f32();
139 let py = buf.get_f32();
140 let pz = buf.get_f32();
141 let rp = buf.get_f32();
142 let ry = buf.get_f32();
143 let rr = buf.get_f32();
144 let sx = buf.get_f32();
145 let sy = buf.get_f32();
146 let sz = buf.get_f32();
147 Ok(SpatialValue::S9(Transform {
148 position: Position3D {
149 x: px,
150 y: py,
151 z: pz,
152 },
153 rotation: Rotation {
154 pitch: rp,
155 yaw: ry,
156 roll: rr,
157 },
158 scale: Position3D {
159 x: sx,
160 y: sy,
161 z: sz,
162 },
163 }))
164 }
165 0x10 | 0x0A => {
166 if buf.remaining() < 1 {
168 return Err(SpatialError::DecodeError(
169 "Insufficient data for SpatialState mask".into(),
170 ));
171 }
172 let mask = buf.get_u8();
173
174 let position = if mask & 0x01 != 0 {
175 if buf.remaining() < 12 {
176 return Err(SpatialError::DecodeError(
177 "Insufficient data for SpatialState Position".into(),
178 ));
179 }
180 Some(Position3D {
181 x: buf.get_f32(),
182 y: buf.get_f32(),
183 z: buf.get_f32(),
184 })
185 } else {
186 None
187 };
188
189 let rotation = if mask & 0x02 != 0 {
190 if buf.remaining() < 12 {
191 return Err(SpatialError::DecodeError(
192 "Insufficient data for SpatialState Rotation".into(),
193 ));
194 }
195 Some(Rotation {
196 pitch: buf.get_f32(),
197 yaw: buf.get_f32(),
198 roll: buf.get_f32(),
199 })
200 } else {
201 None
202 };
203
204 let velocity = if mask & 0x04 != 0 {
205 if buf.remaining() < 12 {
206 return Err(SpatialError::DecodeError(
207 "Insufficient data for SpatialState Velocity".into(),
208 ));
209 }
210 Some(Velocity {
211 vx: buf.get_f32(),
212 vy: buf.get_f32(),
213 vz: buf.get_f32(),
214 })
215 } else {
216 None
217 };
218
219 let acceleration = if mask & 0x08 != 0 {
220 if buf.remaining() < 12 {
221 return Err(SpatialError::DecodeError(
222 "Insufficient data for SpatialState Acceleration".into(),
223 ));
224 }
225 Some(Acceleration {
226 ax: buf.get_f32(),
227 ay: buf.get_f32(),
228 az: buf.get_f32(),
229 })
230 } else {
231 None
232 };
233
234 Ok(SpatialValue::S10(SpatialState {
235 position,
236 rotation,
237 velocity,
238 acceleration,
239 }))
240 }
241 0x0B => {
242 if buf.remaining() < 12 {
244 return Err(SpatialError::DecodeError(
245 "Insufficient data for PositionDelta".into(),
246 ));
247 }
248 let dx = buf.get_f32();
249 let dy = buf.get_f32();
250 let dz = buf.get_f32();
251 Ok(SpatialValue::S11(PositionDelta { dx, dy, dz }))
252 }
253 0x0C => {
254 if buf.remaining() < 12 {
256 return Err(SpatialError::DecodeError(
257 "Insufficient data for RotationDelta".into(),
258 ));
259 }
260 let d_pitch = buf.get_f32();
261 let d_yaw = buf.get_f32();
262 let d_roll = buf.get_f32();
263 Ok(SpatialValue::S12(RotationDelta {
264 d_pitch,
265 d_yaw,
266 d_roll,
267 }))
268 }
269 0x0D => {
270 if buf.remaining() < 1 {
272 return Err(SpatialError::DecodeError(
273 "Insufficient data for SpatialDelta type".into(),
274 ));
275 }
276 let delta_type = buf.get_u8();
277 match delta_type {
278 0x01 => {
279 if buf.remaining() < 12 {
281 return Err(SpatialError::DecodeError(
282 "Insufficient data for SpatialDelta::Position".into(),
283 ));
284 }
285 Ok(SpatialValue::S13(SpatialDelta::Position(PositionDelta {
286 dx: buf.get_f32(),
287 dy: buf.get_f32(),
288 dz: buf.get_f32(),
289 })))
290 }
291 0x02 => {
292 if buf.remaining() < 12 {
294 return Err(SpatialError::DecodeError(
295 "Insufficient data for SpatialDelta::Rotation".into(),
296 ));
297 }
298 Ok(SpatialValue::S13(SpatialDelta::Rotation(RotationDelta {
299 d_pitch: buf.get_f32(),
300 d_yaw: buf.get_f32(),
301 d_roll: buf.get_f32(),
302 })))
303 }
304 0x03 => {
305 if buf.remaining() < 1 {
307 return Err(SpatialError::DecodeError(
308 "Insufficient data for SpatialDelta::State mask".into(),
309 ));
310 }
311 let mask = buf.get_u8();
312
313 let position = if mask & 0x01 != 0 {
314 if buf.remaining() < 12 {
315 return Err(SpatialError::DecodeError(
316 "Insufficient data for SpatialDelta Position".into(),
317 ));
318 }
319 Some(PositionDelta {
320 dx: buf.get_f32(),
321 dy: buf.get_f32(),
322 dz: buf.get_f32(),
323 })
324 } else {
325 None
326 };
327
328 let rotation = if mask & 0x02 != 0 {
329 if buf.remaining() < 12 {
330 return Err(SpatialError::DecodeError(
331 "Insufficient data for SpatialDelta Rotation".into(),
332 ));
333 }
334 Some(RotationDelta {
335 d_pitch: buf.get_f32(),
336 d_yaw: buf.get_f32(),
337 d_roll: buf.get_f32(),
338 })
339 } else {
340 None
341 };
342
343 let velocity = if mask & 0x04 != 0 {
344 if buf.remaining() < 12 {
345 return Err(SpatialError::DecodeError(
346 "Insufficient data for SpatialDelta Velocity".into(),
347 ));
348 }
349 Some(Velocity {
350 vx: buf.get_f32(),
351 vy: buf.get_f32(),
352 vz: buf.get_f32(),
353 })
354 } else {
355 None
356 };
357
358 let acceleration = if mask & 0x08 != 0 {
359 if buf.remaining() < 12 {
360 return Err(SpatialError::DecodeError(
361 "Insufficient data for SpatialDelta Acceleration".into(),
362 ));
363 }
364 Some(Acceleration {
365 ax: buf.get_f32(),
366 ay: buf.get_f32(),
367 az: buf.get_f32(),
368 })
369 } else {
370 None
371 };
372
373 Ok(SpatialValue::S13(SpatialDelta::State {
374 position,
375 rotation,
376 velocity,
377 acceleration,
378 }))
379 }
380 _ => Err(SpatialError::DecodeError(format!(
381 "Unknown SpatialDelta type: {}",
382 delta_type
383 ))),
384 }
385 }
386 _ => Err(SpatialError::UnknownType(type_id)),
387 }
388}