box3d_rust/recording/
buffer.rs1use crate::geometry::{Capsule, Sphere, SurfaceMaterial};
8use crate::math_functions::{Aabb, Matrix3, Pos, Quat, Transform, Vec3, WorldTransform};
9use crate::types::Filter;
10
11#[derive(Debug, Clone, Default)]
14pub struct RecBuffer {
15 pub data: Vec<u8>,
16 pub count_only: bool,
17}
18
19impl RecBuffer {
20 pub fn new() -> Self {
22 Self {
23 data: Vec::new(),
24 count_only: false,
25 }
26 }
27
28 pub fn with_capacity(cap: usize) -> Self {
29 Self {
30 data: Vec::with_capacity(cap),
31 count_only: false,
32 }
33 }
34
35 pub fn size(&self) -> i32 {
36 self.data.len() as i32
37 }
38
39 pub fn append(&mut self, bytes: &[u8]) {
41 if bytes.is_empty() {
42 return;
43 }
44 if self.count_only {
45 let new_len = self.data.len() + bytes.len();
49 self.data.resize(new_len, 0);
55 return;
56 }
57 self.data.extend_from_slice(bytes);
58 }
59
60 pub fn append_u8(&mut self, v: u8) {
61 self.append(&[v]);
62 }
63
64 pub fn append_u16(&mut self, v: u16) {
65 self.append(&v.to_le_bytes());
66 }
67
68 pub fn append_u32(&mut self, v: u32) {
69 self.append(&v.to_le_bytes());
70 }
71
72 pub fn append_u64(&mut self, v: u64) {
73 self.append(&v.to_le_bytes());
74 }
75
76 pub fn append_i32(&mut self, v: i32) {
77 self.append_u32(v as u32);
78 }
79
80 pub fn append_f32(&mut self, v: f32) {
81 self.append(&v.to_le_bytes());
82 }
83
84 pub fn append_f64(&mut self, v: f64) {
85 self.append(&v.to_le_bytes());
86 }
87
88 pub fn append_bool(&mut self, v: bool) {
89 self.append_u8(u8::from(v));
90 }
91
92 pub fn append_vec3(&mut self, v: Vec3) {
93 self.append_f32(v.x);
94 self.append_f32(v.y);
95 self.append_f32(v.z);
96 }
97
98 pub fn append_quat(&mut self, v: Quat) {
99 self.append_vec3(v.v);
100 self.append_f32(v.s);
101 }
102
103 pub fn append_transform(&mut self, v: Transform) {
104 self.append_vec3(v.p);
105 self.append_quat(v.q);
106 }
107
108 pub fn append_pos(&mut self, v: Pos) {
109 #[cfg(feature = "double-precision")]
110 {
111 self.append_f64(v.x);
112 self.append_f64(v.y);
113 self.append_f64(v.z);
114 }
115 #[cfg(not(feature = "double-precision"))]
116 {
117 self.append_vec3(v);
118 }
119 }
120
121 pub fn append_world_xf(&mut self, v: WorldTransform) {
122 #[cfg(feature = "double-precision")]
123 {
124 self.append_pos(v.p);
125 self.append_quat(v.q);
126 }
127 #[cfg(not(feature = "double-precision"))]
128 {
129 self.append_transform(v);
130 }
131 }
132
133 pub fn append_matrix3(&mut self, v: Matrix3) {
134 self.append_vec3(v.cx);
135 self.append_vec3(v.cy);
136 self.append_vec3(v.cz);
137 }
138
139 pub fn append_aabb(&mut self, v: Aabb) {
140 self.append_vec3(v.lower_bound);
141 self.append_vec3(v.upper_bound);
142 }
143
144 pub fn append_sphere(&mut self, v: Sphere) {
145 self.append_vec3(v.center);
146 self.append_f32(v.radius);
147 }
148
149 pub fn append_capsule(&mut self, v: Capsule) {
150 self.append_vec3(v.center1);
151 self.append_vec3(v.center2);
152 self.append_f32(v.radius);
153 }
154
155 pub fn append_filter(&mut self, v: Filter) {
156 self.append_u64(v.category_bits);
157 self.append_u64(v.mask_bits);
158 self.append_i32(v.group_index);
159 }
160
161 pub fn append_material(&mut self, v: SurfaceMaterial) {
162 self.append_f32(v.friction);
163 self.append_f32(v.restitution);
164 self.append_f32(v.rolling_resistance);
165 self.append_vec3(v.tangent_velocity);
166 self.append_u64(v.user_material_id);
167 self.append_u32(v.custom_color);
168 }
169}
170
171#[derive(Debug, Clone)]
173pub struct SnapReader<'a> {
174 data: &'a [u8],
175 cursor: usize,
176 pub ok: bool,
177}
178
179impl<'a> SnapReader<'a> {
180 pub fn new(data: &'a [u8]) -> Self {
181 Self {
182 data,
183 cursor: 0,
184 ok: true,
185 }
186 }
187
188 pub fn cursor(&self) -> usize {
189 self.cursor
190 }
191
192 pub fn set_cursor(&mut self, cursor: usize) {
193 self.cursor = cursor;
194 }
195
196 fn check(&mut self, need: usize) {
197 if !self.ok {
198 return;
199 }
200 if self
201 .cursor
202 .checked_add(need)
203 .map(|e| e > self.data.len())
204 .unwrap_or(true)
205 {
206 self.ok = false;
207 }
208 }
209
210 pub fn bytes(&mut self, n: usize) -> Option<&'a [u8]> {
211 self.check(n);
212 if !self.ok {
213 return None;
214 }
215 let start = self.cursor;
216 self.cursor += n;
217 Some(&self.data[start..self.cursor])
218 }
219
220 pub fn copy_bytes(&mut self, dst: &mut [u8]) {
221 if let Some(src) = self.bytes(dst.len()) {
222 dst.copy_from_slice(src);
223 }
224 }
225
226 pub fn u8(&mut self) -> u8 {
227 self.bytes(1).map(|b| b[0]).unwrap_or(0)
228 }
229
230 pub fn u16(&mut self) -> u16 {
231 let mut b = [0u8; 2];
232 self.copy_bytes(&mut b);
233 u16::from_le_bytes(b)
234 }
235
236 pub fn u32(&mut self) -> u32 {
237 let mut b = [0u8; 4];
238 self.copy_bytes(&mut b);
239 u32::from_le_bytes(b)
240 }
241
242 pub fn u64(&mut self) -> u64 {
243 let mut b = [0u8; 8];
244 self.copy_bytes(&mut b);
245 u64::from_le_bytes(b)
246 }
247
248 pub fn i32(&mut self) -> i32 {
249 self.u32() as i32
250 }
251
252 pub fn f32(&mut self) -> f32 {
253 f32::from_le_bytes(self.u32().to_le_bytes())
254 }
255
256 pub fn f64(&mut self) -> f64 {
257 f64::from_le_bytes(self.u64().to_le_bytes())
258 }
259
260 pub fn bool(&mut self) -> bool {
261 self.u8() != 0
262 }
263
264 pub fn vec3(&mut self) -> Vec3 {
265 Vec3 {
266 x: self.f32(),
267 y: self.f32(),
268 z: self.f32(),
269 }
270 }
271
272 pub fn quat(&mut self) -> Quat {
273 Quat {
274 v: self.vec3(),
275 s: self.f32(),
276 }
277 }
278
279 pub fn transform(&mut self) -> Transform {
280 Transform {
281 p: self.vec3(),
282 q: self.quat(),
283 }
284 }
285
286 pub fn pos(&mut self) -> Pos {
287 #[cfg(feature = "double-precision")]
288 {
289 Pos {
290 x: self.f64(),
291 y: self.f64(),
292 z: self.f64(),
293 }
294 }
295 #[cfg(not(feature = "double-precision"))]
296 {
297 self.vec3()
298 }
299 }
300
301 pub fn world_xf(&mut self) -> WorldTransform {
302 #[cfg(feature = "double-precision")]
303 {
304 WorldTransform {
305 p: self.pos(),
306 q: self.quat(),
307 }
308 }
309 #[cfg(not(feature = "double-precision"))]
310 {
311 self.transform()
312 }
313 }
314
315 pub fn matrix3(&mut self) -> Matrix3 {
316 Matrix3 {
317 cx: self.vec3(),
318 cy: self.vec3(),
319 cz: self.vec3(),
320 }
321 }
322
323 pub fn aabb(&mut self) -> Aabb {
324 Aabb {
325 lower_bound: self.vec3(),
326 upper_bound: self.vec3(),
327 }
328 }
329
330 pub fn sphere(&mut self) -> Sphere {
331 Sphere {
332 center: self.vec3(),
333 radius: self.f32(),
334 }
335 }
336
337 pub fn capsule(&mut self) -> Capsule {
338 Capsule {
339 center1: self.vec3(),
340 center2: self.vec3(),
341 radius: self.f32(),
342 }
343 }
344
345 pub fn filter(&mut self) -> Filter {
346 Filter {
347 category_bits: self.u64(),
348 mask_bits: self.u64(),
349 group_index: self.i32(),
350 }
351 }
352
353 pub fn material(&mut self) -> SurfaceMaterial {
354 SurfaceMaterial {
355 friction: self.f32(),
356 restitution: self.f32(),
357 rolling_resistance: self.f32(),
358 tangent_velocity: self.vec3(),
359 user_material_id: self.u64(),
360 custom_color: self.u32(),
361 }
362 }
363
364 pub fn check_count(&self, count: i32, mem_size: i32, min_stream_bytes: i32) -> bool {
366 if count < 0 || mem_size < 0 || min_stream_bytes < 0 {
367 return false;
368 }
369 if mem_size > 0 && count > 0 && count > i32::MAX / mem_size {
370 return false;
371 }
372 let remaining = self.data.len() as i64 - self.cursor as i64;
373 (count as i64) * (min_stream_bytes as i64) <= remaining
374 }
375}