1use super::write::{rec_w_i32, rec_w_u16, rec_w_u32, rec_w_u64};
17use crate::bitset::BitSet;
18use crate::dynamic_tree::{DynamicTree, TreeNode};
19use crate::id_pool::IdPool;
20use crate::math_functions::{Aabb, Vec2};
21use crate::table::HashSet;
22
23pub const SNAP_MAGIC: u32 = 0x32534E42;
25
26pub const SNAP_VERSION: u32 = 1;
29
30pub const SNAP_FLAG_VALIDATION: u32 = 0x1;
32pub const SNAP_FLAG_DOUBLE_PRECISION: u32 = 0x2;
35
36pub fn compute_layout_hash() -> u32 {
40 let mut h: u32 = 2166136261;
41 let mut mix = |x: usize| {
42 h ^= x as u32;
43 h = h.wrapping_mul(16777619);
44 };
45 mix(std::mem::size_of::<crate::body::Body>());
46 mix(std::mem::size_of::<crate::body::BodySim>());
47 mix(std::mem::size_of::<crate::body::BodyState>());
48 mix(std::mem::size_of::<crate::shape::Shape>());
49 mix(std::mem::size_of::<crate::shape::ChainShape>());
50 mix(std::mem::size_of::<crate::contact::Contact>());
51 mix(std::mem::size_of::<crate::contact::ContactSim>());
52 mix(std::mem::size_of::<crate::joint::Joint>());
53 mix(std::mem::size_of::<crate::joint::JointSim>());
54 mix(std::mem::size_of::<crate::island::Island>());
55 mix(std::mem::size_of::<crate::island::IslandSim>());
56 mix(std::mem::size_of::<TreeNode>());
57 mix(std::mem::size_of::<crate::sensor::Sensor>());
58 mix(crate::constants::GRAPH_COLOR_COUNT as usize);
59 h
60}
61
62#[derive(Debug, Clone, Copy, PartialEq, Eq)]
64pub struct SnapHeader {
65 pub magic: u32,
66 pub version: u32,
67 pub layout_hash: u32,
68 pub flags: u32,
69}
70
71impl SnapHeader {
72 pub const SIZE: usize = 16;
73
74 pub fn current() -> SnapHeader {
76 let mut flags = 0;
77 if cfg!(debug_assertions) {
78 flags |= SNAP_FLAG_VALIDATION;
79 }
80 if crate::core::is_double_precision() {
81 flags |= SNAP_FLAG_DOUBLE_PRECISION;
82 }
83 SnapHeader {
84 magic: SNAP_MAGIC,
85 version: SNAP_VERSION,
86 layout_hash: compute_layout_hash(),
87 flags,
88 }
89 }
90
91 pub fn write(&self, buf: &mut Vec<u8>) {
92 rec_w_u32(buf, self.magic);
93 rec_w_u32(buf, self.version);
94 rec_w_u32(buf, self.layout_hash);
95 rec_w_u32(buf, self.flags);
96 }
97
98 pub fn is_compatible(&self) -> bool {
101 let current = SnapHeader::current();
102 self.magic == SNAP_MAGIC
103 && self.version == SNAP_VERSION
104 && self.layout_hash == current.layout_hash
105 && (self.flags & SNAP_FLAG_DOUBLE_PRECISION)
106 == (current.flags & SNAP_FLAG_DOUBLE_PRECISION)
107 }
108}
109
110#[derive(Debug)]
114pub struct SnapReader<'a> {
115 pub data: &'a [u8],
116 pub cursor: usize,
117 pub ok: bool,
118}
119
120impl<'a> SnapReader<'a> {
121 pub fn new(data: &'a [u8]) -> SnapReader<'a> {
122 SnapReader {
123 data,
124 cursor: 0,
125 ok: true,
126 }
127 }
128
129 fn take(&mut self, n: usize) -> &'a [u8] {
130 if !self.ok || self.cursor + n > self.data.len() {
131 self.ok = false;
132 return &[];
133 }
134 let slice = &self.data[self.cursor..self.cursor + n];
135 self.cursor += n;
136 slice
137 }
138
139 pub fn r_u16(&mut self) -> u16 {
140 let b = self.take(2);
141 if b.len() < 2 {
142 return 0;
143 }
144 u16::from_le_bytes([b[0], b[1]])
145 }
146
147 pub fn r_u32(&mut self) -> u32 {
148 let b = self.take(4);
149 if b.len() < 4 {
150 return 0;
151 }
152 u32::from_le_bytes([b[0], b[1], b[2], b[3]])
153 }
154
155 pub fn r_i32(&mut self) -> i32 {
156 self.r_u32() as i32
157 }
158
159 pub fn r_u64(&mut self) -> u64 {
160 let b = self.take(8);
161 if b.len() < 8 {
162 return 0;
163 }
164 u64::from_le_bytes([b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]])
165 }
166
167 pub fn r_f32(&mut self) -> f32 {
168 f32::from_bits(self.r_u32())
169 }
170
171 pub fn r_f64(&mut self) -> f64 {
172 f64::from_bits(self.r_u64())
173 }
174
175 pub fn r_bool(&mut self) -> bool {
176 let b = self.take(1);
177 !b.is_empty() && b[0] != 0
178 }
179
180 pub fn r_u8(&mut self) -> u8 {
181 let b = self.take(1);
182 if b.is_empty() {
183 0
184 } else {
185 b[0]
186 }
187 }
188
189 pub fn check_count(&mut self, count: i32, min_stream_bytes: usize) -> bool {
192 if count < 0
193 || (count as usize) * min_stream_bytes
194 > self.data.len() - self.cursor.min(self.data.len())
195 {
196 self.ok = false;
197 return false;
198 }
199 true
200 }
201
202 pub fn r_header(&mut self) -> SnapHeader {
203 SnapHeader {
204 magic: self.r_u32(),
205 version: self.r_u32(),
206 layout_hash: self.r_u32(),
207 flags: self.r_u32(),
208 }
209 }
210}
211
212pub(crate) fn ser_id_pool(buf: &mut Vec<u8>, pool: &IdPool) {
216 rec_w_i32(buf, pool.free_array.len() as i32);
217 for &id in pool.free_array.iter() {
218 rec_w_i32(buf, id);
219 }
220 rec_w_i32(buf, pool.next_index);
221}
222
223pub(crate) fn des_id_pool(r: &mut SnapReader) -> IdPool {
224 let count = r.r_i32();
225 if !r.check_count(count, 4) {
226 return IdPool::new();
227 }
228 let mut pool = IdPool::new();
229 pool.free_array = (0..count).map(|_| r.r_i32()).collect();
230 pool.next_index = r.r_i32();
231 pool
232}
233
234pub(crate) fn ser_bitset(buf: &mut Vec<u8>, bs: &BitSet) {
235 rec_w_u32(buf, bs.block_count);
236 rec_w_i32(buf, bs.blocks.len() as i32);
237 for &block in bs.blocks.iter() {
238 rec_w_u64(buf, block);
239 }
240}
241
242pub(crate) fn des_bitset(r: &mut SnapReader) -> BitSet {
243 let block_count = r.r_u32();
244 let capacity = r.r_i32();
245 if !r.check_count(capacity, 8) {
246 return BitSet::new(0);
247 }
248 let mut bs = BitSet::new(0);
249 bs.block_count = block_count;
250 bs.blocks = (0..capacity).map(|_| r.r_u64()).collect();
251 bs
252}
253
254pub(crate) fn ser_hashset(buf: &mut Vec<u8>, hs: &HashSet) {
255 rec_w_u32(buf, hs.count);
256 rec_w_i32(buf, hs.items.len() as i32);
257 for &item in hs.items.iter() {
258 rec_w_u64(buf, item);
259 }
260}
261
262pub(crate) fn des_hashset(r: &mut SnapReader) -> HashSet {
263 let count = r.r_u32();
264 let capacity = r.r_i32();
265 if !r.check_count(capacity, 8) {
266 return HashSet::new(16);
267 }
268 let mut hs = HashSet::new(16);
269 hs.count = count;
270 hs.items = (0..capacity).map(|_| r.r_u64()).collect();
271 hs
272}
273
274fn ser_aabb(buf: &mut Vec<u8>, aabb: Aabb) {
275 super::write::rec_w_f32(buf, aabb.lower_bound.x);
276 super::write::rec_w_f32(buf, aabb.lower_bound.y);
277 super::write::rec_w_f32(buf, aabb.upper_bound.x);
278 super::write::rec_w_f32(buf, aabb.upper_bound.y);
279}
280
281fn des_aabb(r: &mut SnapReader) -> Aabb {
282 Aabb {
283 lower_bound: Vec2 {
284 x: r.r_f32(),
285 y: r.r_f32(),
286 },
287 upper_bound: Vec2 {
288 x: r.r_f32(),
289 y: r.r_f32(),
290 },
291 }
292}
293
294pub(crate) fn ser_tree(buf: &mut Vec<u8>, tree: &DynamicTree) {
295 rec_w_i32(buf, tree.root);
296 rec_w_i32(buf, tree.node_count);
297 rec_w_i32(buf, tree.free_list);
298 rec_w_i32(buf, tree.proxy_count);
299 rec_w_i32(buf, tree.nodes.len() as i32);
300 for node in tree.nodes.iter() {
301 ser_aabb(buf, node.aabb);
302 rec_w_u64(buf, node.category_bits);
303 rec_w_i32(buf, node.child1);
304 rec_w_i32(buf, node.child2);
305 rec_w_u64(buf, node.user_data);
306 rec_w_i32(buf, node.parent);
307 rec_w_i32(buf, node.next);
308 rec_w_u16(buf, node.height);
309 rec_w_u16(buf, node.flags);
310 }
311 }
315
316pub(crate) fn des_tree(r: &mut SnapReader) -> DynamicTree {
317 let mut tree = DynamicTree::new(0);
318 tree.root = r.r_i32();
319 tree.node_count = r.r_i32();
320 tree.free_list = r.r_i32();
321 tree.proxy_count = r.r_i32();
322 let capacity = r.r_i32();
323 if !r.check_count(capacity, 48) {
325 return DynamicTree::new(0);
326 }
327 tree.nodes = (0..capacity)
328 .map(|_| {
329 let mut node = TreeNode::default_node();
330 node.aabb = des_aabb(r);
331 node.category_bits = r.r_u64();
332 node.child1 = r.r_i32();
333 node.child2 = r.r_i32();
334 node.user_data = r.r_u64();
335 node.parent = r.r_i32();
336 node.next = r.r_i32();
337 node.height = r.r_u16();
338 node.flags = r.r_u16();
339 node
340 })
341 .collect();
342 tree
343}
344
345#[cfg(test)]
346mod tests {
347 use super::*;
348
349 #[test]
352 fn container_round_trips() {
353 let mut pool = IdPool::new();
355 for _ in 0..6 {
356 pool.alloc_id();
357 }
358 pool.free_id(2);
359 pool.free_id(4);
360 let mut buf = Vec::new();
361 ser_id_pool(&mut buf, &pool);
362 let mut r = SnapReader::new(&buf);
363 let restored = des_id_pool(&mut r);
364 assert!(r.ok);
365 assert_eq!(restored.id_count(), pool.id_count());
366 assert_eq!(restored.id_capacity(), pool.id_capacity());
367
368 let mut bs = BitSet::new(200);
370 bs.set_bit_count_and_clear(200);
371 bs.set_bit(3);
372 bs.set_bit(130);
373 let mut buf = Vec::new();
374 ser_bitset(&mut buf, &bs);
375 let mut r = SnapReader::new(&buf);
376 let restored = des_bitset(&mut r);
377 assert!(r.ok);
378 assert!(restored.get_bit(3) && restored.get_bit(130) && !restored.get_bit(64));
379
380 let mut hs = HashSet::new(16);
382 hs.add_key(crate::table::shape_pair_key(3, 9));
383 hs.add_key(crate::table::shape_pair_key(1, 2));
384 let mut buf = Vec::new();
385 ser_hashset(&mut buf, &hs);
386 let mut r = SnapReader::new(&buf);
387 let restored = des_hashset(&mut r);
388 assert!(r.ok);
389 assert!(restored.contains_key(crate::table::shape_pair_key(3, 9)));
390 assert!(!restored.contains_key(crate::table::shape_pair_key(3, 8)));
391
392 let mut tree = DynamicTree::new(4);
394 for i in 0..5 {
395 let x = i as f32;
396 tree.create_proxy(
397 Aabb {
398 lower_bound: Vec2 { x, y: 0.0 },
399 upper_bound: Vec2 { x: x + 1.0, y: 1.0 },
400 },
401 1,
402 i as u64,
403 );
404 }
405 let mut buf = Vec::new();
406 ser_tree(&mut buf, &tree);
407 let mut r = SnapReader::new(&buf);
408 let restored = des_tree(&mut r);
409 assert!(r.ok);
410 assert_eq!(restored.proxy_count(), 5);
411 assert_eq!(restored.height(), tree.height());
412 restored.validate();
413
414 let mut short = SnapReader::new(&buf[..10]);
416 let _ = des_tree(&mut short);
417 assert!(!short.ok);
418 }
419
420 #[test]
421 fn header_compatibility() {
422 let header = SnapHeader::current();
423 let mut buf = Vec::new();
424 header.write(&mut buf);
425 assert_eq!(buf.len(), SnapHeader::SIZE);
426
427 let mut r = SnapReader::new(&buf);
428 let read = r.r_header();
429 assert!(r.ok);
430 assert_eq!(read, header);
431 assert!(read.is_compatible());
432
433 let foreign = SnapHeader {
435 layout_hash: header.layout_hash ^ 1,
436 ..header
437 };
438 assert!(!foreign.is_compatible());
439 }
440}