1use std::collections::HashMap;
18
19use anyhow::{anyhow, bail, Result};
20
21const MAX_NODES: usize = 20_000_000;
24const MAX_ARRAY: usize = 50_000_000;
26
27#[derive(Debug, Default)]
29pub struct Tree {
30 pub fields: Vec<Field>,
31 pub nodes: Vec<Node>,
32}
33
34#[derive(Debug, Clone)]
35pub struct Field {
36 pub ty: u8,
37 pub name: String,
38 dims: Option<Vec<usize>>,
39}
40
41#[derive(Debug, Clone)]
42pub enum Node {
43 Null,
44 Int(i64),
45 Dbl(f64),
46 Str(String),
47 List(Vec<usize>),
49 Struct(Vec<(u32, usize)>),
51}
52
53impl Tree {
54 pub fn root(&self) -> usize {
55 0
56 }
57
58 pub fn node(&self, i: usize) -> &Node {
59 self.nodes.get(i).unwrap_or(&Node::Null)
60 }
61
62 pub fn child(&self, i: usize, name: &str) -> Option<usize> {
64 match self.node(i) {
65 Node::Struct(kids) => kids
66 .iter()
67 .find(|(f, _)| {
68 self.fields
69 .get(*f as usize)
70 .is_some_and(|fd| fd.name == name)
71 })
72 .map(|(_, c)| *c),
73 _ => None,
74 }
75 }
76
77 pub fn children_with_prefix(&self, i: usize, prefix: &str) -> Vec<(&str, usize)> {
80 match self.node(i) {
81 Node::Struct(kids) => kids
82 .iter()
83 .filter_map(|(f, c)| {
84 let name = self.fields.get(*f as usize)?.name.as_str();
85 name.starts_with(prefix).then_some((name, *c))
86 })
87 .collect(),
88 _ => Vec::new(),
89 }
90 }
91
92 pub fn children(&self, i: usize, name: &str) -> Vec<usize> {
94 match self.node(i) {
95 Node::Struct(kids) => kids
96 .iter()
97 .filter(|(f, _)| {
98 self.fields
99 .get(*f as usize)
100 .is_some_and(|fd| fd.name == name)
101 })
102 .map(|(_, c)| *c)
103 .collect(),
104 _ => Vec::new(),
105 }
106 }
107
108 pub fn int(&self, i: usize) -> Option<i64> {
109 match self.node(i) {
110 Node::Int(v) => Some(*v),
111 Node::Dbl(v) if v.fract() == 0.0 => Some(*v as i64),
112 _ => None,
113 }
114 }
115
116 pub fn int_at(&self, i: usize, name: &str) -> Option<i64> {
117 self.child(i, name).and_then(|c| self.int(c))
118 }
119
120 pub fn dbl(&self, i: usize) -> Option<f64> {
121 match self.node(i) {
122 Node::Dbl(v) => Some(*v),
123 Node::Int(v) => Some(*v as f64),
124 _ => None,
125 }
126 }
127
128 pub fn dbl_at(&self, i: usize, name: &str) -> Option<f64> {
129 self.child(i, name).and_then(|c| self.dbl(c))
130 }
131
132 pub fn list(&self, i: usize) -> &[usize] {
133 match self.node(i) {
134 Node::List(v) => v,
135 _ => &[],
136 }
137 }
138
139 pub fn dbls(&self, i: usize) -> Vec<f64> {
141 self.list(i)
142 .iter()
143 .map(|&c| self.dbl(c).unwrap_or(f64::NAN))
144 .collect()
145 }
146
147 pub fn rows(&self, i: usize) -> Vec<Vec<f64>> {
149 self.list(i).iter().map(|&r| self.dbls(r)).collect()
150 }
151
152 pub fn str_at(&self, i: usize, name: &str) -> Option<&str> {
153 match self.child(i, name).map(|c| self.node(c)) {
154 Some(Node::Str(s)) => Some(s.as_str()),
155 _ => None,
156 }
157 }
158}
159
160struct Frame {
161 field: u32,
162 node: usize,
163 is_array: bool,
164 left: usize,
166 extra: Option<usize>,
168}
169
170struct Reader<'a> {
171 d: &'a [u8],
172 p: usize,
173 tree: Tree,
174 trans: HashMap<u32, (usize, u32)>,
176 stack: Vec<Frame>,
177 explicit: bool,
178}
179
180pub fn parse(data: &[u8]) -> Result<Tree> {
182 let mut r = Reader {
183 d: data,
184 p: 0,
185 tree: Tree::default(),
186 trans: HashMap::new(),
187 stack: Vec::new(),
188 explicit: false,
189 };
190 r.run()?;
191 Ok(r.tree)
192}
193
194impl<'a> Reader<'a> {
195 fn byte(&mut self) -> Result<u8> {
196 let b = *self
197 .d
198 .get(self.p)
199 .ok_or_else(|| anyhow!("section ends inside a value"))?;
200 self.p += 1;
201 Ok(b)
202 }
203
204 fn peek(&self) -> Option<u8> {
205 self.d.get(self.p).copied()
206 }
207
208 fn rest(&self) -> &'a [u8] {
210 self.d.get(self.p..).unwrap_or_default()
211 }
212
213 fn field(&self, f: u32) -> Result<&Field> {
214 self.tree
215 .fields
216 .get(f as usize)
217 .ok_or_else(|| anyhow!("unknown field {f}"))
218 }
219
220 fn set_dims(&mut self, f: u32, dims: Vec<usize>) {
221 if let Some(fld) = self.tree.fields.get_mut(f as usize) {
222 fld.dims = Some(dims);
223 }
224 }
225
226 fn take(&mut self, n: usize) -> Result<&'a [u8]> {
227 let end = self
228 .p
229 .checked_add(n)
230 .filter(|&e| e <= self.d.len())
231 .ok_or_else(|| anyhow!("section ends inside a value"))?;
232 let s = self.d.get(self.p..end).unwrap_or_default();
233 self.p = end;
234 Ok(s)
235 }
236
237 fn read_int(&mut self) -> Result<i64> {
238 let mut negate = false;
241 let mut b = self.byte()?;
242 while b == 0xf5 {
243 negate = !negate;
244 b = self.byte()?;
245 }
246 let v = self.read_int_after(b)?;
247 Ok(if negate {
248 v.checked_neg()
249 .ok_or_else(|| anyhow!("integer out of range"))?
250 } else {
251 v
252 })
253 }
254
255 fn read_int_after(&mut self, b: u8) -> Result<i64> {
256 Ok(match b {
257 0x00..=0x7f => i64::from(b),
258 0x80..=0xbf => (i64::from(b & 0x3f) << 8) | i64::from(self.byte()?),
259 0xc0..=0xdf => {
260 let hi = i64::from(b & 0x1f) << 16;
261 let m = i64::from(self.byte()?) << 8;
262 hi | m | i64::from(self.byte()?)
263 }
264 0xe8..=0xeb => {
265 let n = usize::from(b - 0xe7);
266 let s = self.take(n)?;
267 let mut v: i64 = 0;
268 for &x in s {
269 v = (v << 8) | i64::from(x);
270 }
271 if n == 4 {
272 v = i64::from(v as u32 as i32);
273 }
274 v
275 }
276 0xf6 => -1,
277 other => bail!("integer token {other:02x} at {}", self.p - 1),
278 })
279 }
280
281 fn read_string(&mut self) -> Result<Node> {
282 if self.peek() == Some(0xe1) {
283 self.p += 1;
284 return Ok(Node::Null);
285 }
286 let rest = self.rest();
287 let end = rest
288 .iter()
289 .position(|&b| b == 0)
290 .ok_or_else(|| anyhow!("unterminated string"))?;
291 let s = String::from_utf8_lossy(rest.get(..end).unwrap_or_default()).into_owned();
292 self.p += end + 1;
293 Ok(Node::Str(s))
294 }
295
296 fn read_scalar(&mut self, ty: u8) -> Result<Node> {
297 Ok(match ty {
298 0x02 => {
299 let (v, n) = double::decode(self.rest())?;
300 self.p += n;
301 Node::Dbl(v)
302 }
303 0x03 | 0x0a => self.read_string()?,
304 0x06 => {
305 let (v, n) = double::decode_float(self.rest())?;
306 self.p += n;
307 Node::Dbl(v)
308 }
309 _ => Node::Int(self.read_int()?),
310 })
311 }
312
313 fn read_values(&mut self, ty: u8, count: usize) -> Result<Vec<usize>> {
314 if count > MAX_ARRAY {
315 bail!("array of {count} elements");
316 }
317 let mut out: Vec<usize> = Vec::new();
318 while out.len() < count {
319 if let (Some(b @ 0xe4..=0xe7), Some(&last)) = (self.peek(), out.last()) {
320 self.p += 1;
321 let n = if b == 0xe7 {
322 usize::try_from(self.read_int()?).unwrap_or(usize::MAX)
323 } else {
324 usize::from(b - 0xe3)
325 };
326 if out.len().saturating_add(n) > count {
327 bail!("array repeat beyond the array");
328 }
329 out.extend(std::iter::repeat_n(last, n));
330 continue;
331 }
332 let v = self.read_scalar(ty)?;
333 out.push(self.push(v)?);
334 }
335 Ok(out)
336 }
337
338 fn push(&mut self, n: Node) -> Result<usize> {
339 if self.tree.nodes.len() >= MAX_NODES {
340 bail!("section with more than {MAX_NODES} values");
341 }
342 self.tree.nodes.push(n);
343 Ok(self.tree.nodes.len() - 1)
344 }
345
346 fn dim(&mut self) -> Result<usize> {
347 let v = self.read_int()?;
348 usize::try_from(v)
349 .ok()
350 .filter(|&n| n <= MAX_ARRAY)
351 .ok_or_else(|| anyhow!("array dimension {v}"))
352 }
353
354 fn shaped(&mut self, ty: u8, dims: &[usize]) -> Result<Node> {
355 let total = dims
356 .iter()
357 .try_fold(1usize, |a, &d| a.checked_mul(d))
358 .filter(|&n| n <= MAX_ARRAY)
359 .ok_or_else(|| anyhow!("array too large"))?;
360 let flat = self.read_values(ty, total)?;
361 if let [r, c] = *dims {
362 if c == 0 {
363 return Ok(Node::List(flat));
364 }
365 let mut rows = Vec::with_capacity(r);
366 for chunk in flat.chunks(c) {
367 rows.push(self.push(Node::List(chunk.to_vec()))?);
368 }
369 return Ok(Node::List(rows));
370 }
371 Ok(Node::List(flat))
372 }
373
374 fn read_leaf(&mut self, field: u32) -> Result<Node> {
375 let ty = self.field(field)?.ty;
376 let dims = self.field(field)?.dims.clone();
377 match self.peek() {
378 Some(0xf8) => {
379 self.p += 1;
380 let n = self.dim()?;
381 self.set_dims(field, vec![n]);
382 self.shaped(ty, &[n])
383 }
384 Some(0xfc) if dims.as_ref().is_some_and(|d| d.len() == 2) => {
385 self.p += 1;
386 let r = self.dim()?;
387 let c = dims.as_ref().and_then(|d| d.get(1)).copied().unwrap_or(0);
388 self.set_dims(field, vec![r, c]);
389 self.shaped(ty, &[r, c])
390 }
391 Some(0xf9) => {
392 self.p += 1;
393 let r = self.dim()?;
394 let c = self.dim()?;
395 self.set_dims(field, vec![r, c]);
396 self.shaped(ty, &[r, c])
397 }
398 Some(0xfa) => {
399 self.p += 1;
400 let k = self.dim()?;
401 if k > 8 {
402 bail!("{k}-dimensional array");
403 }
404 let mut ds = Vec::with_capacity(k);
405 for _ in 0..k {
406 ds.push(self.dim()?);
407 }
408 self.set_dims(field, ds.clone());
409 let total = ds
411 .iter()
412 .try_fold(1usize, |a, &d| a.checked_mul(d))
413 .filter(|&n| n <= MAX_ARRAY)
414 .ok_or_else(|| anyhow!("array too large"))?;
415 Ok(Node::List(self.read_values(ty, total)?))
416 }
417 _ => match dims {
418 Some(ds) => self.shaped(ty, &ds),
419 None => self.read_scalar(ty),
420 },
421 }
422 }
423
424 fn read_def(&mut self) -> Result<u32> {
425 if self.byte()? != 0xe0 {
426 bail!("field definition expected");
427 }
428 let ty = self.byte()?;
429 let Node::Str(name) = self.read_string()? else {
430 bail!("field without name");
431 };
432 if self.tree.fields.len() >= u32::MAX as usize / 2 {
433 bail!("too many fields");
434 }
435 self.tree.fields.push(Field {
436 ty,
437 name,
438 dims: None,
439 });
440 Ok(self.tree.fields.len() as u32 - 1)
441 }
442
443 fn read_closes(&mut self) -> Result<usize> {
444 let mut n = 0usize;
445 self.explicit = false;
446 loop {
447 match self.peek() {
448 Some(b @ 0xf1..=0xf3) => {
449 self.explicit = true;
450 self.p += 1;
451 n += usize::from(b - 0xf0);
452 }
453 Some(0xf4) => {
454 self.explicit = true;
455 self.p += 1;
456 n = n.saturating_add(usize::try_from(self.read_int()?).unwrap_or(usize::MAX));
457 }
458 Some(0xf0) => {
459 self.explicit = true;
460 self.p += 1;
461 }
462 _ => return Ok(n),
463 }
464 }
465 }
466
467 fn close(&mut self, n: usize) -> Result<()> {
468 for _ in 0..n {
469 if self.stack.len() <= 1 {
470 bail!("more levels closed than open at {}", self.p);
471 }
472 self.stack.pop();
473 }
474 Ok(())
475 }
476
477 fn run(&mut self) -> Result<()> {
478 let root_field = self.read_def()?;
479 let tok = self.byte()?;
480 if self.field(root_field)?.ty != 0 || !(tok == 0xe2 || tok == 0xe3) {
481 bail!("section does not start with a struct");
482 }
483 let root = self.push(Node::Struct(Vec::new()))?;
484 self.stack.push(Frame {
485 field: root_field,
486 node: root,
487 is_array: false,
488 left: 0,
489 extra: None,
490 });
491 let mut key = root_field;
492 let mut last_p = usize::MAX;
493 let mut stall = 0;
494 while self.p < self.d.len() {
495 if self.p == last_p {
496 stall += 1;
497 if stall > 50 {
498 bail!("parser stalled at {}", self.p);
499 }
500 } else {
501 stall = 0;
502 }
503 last_p = self.p;
504 let mut closes = self.read_closes()?;
505 let Some(b) = self.peek() else { break };
506 let mut explicit = self.explicit;
507 let next: u32;
508 if b == 0xf7 || b == 0xe0 {
509 if b == 0xf7 {
510 self.p += 1;
511 let id = self.read_int()?;
512 next = u32::try_from(id)
514 .ok()
515 .and_then(|i| i.checked_sub(1))
516 .filter(|&i| (i as usize) < self.tree.fields.len())
517 .ok_or_else(|| anyhow!("unknown field {id}"))?;
518 } else {
519 next = self.read_def()?;
520 }
521 closes += self.read_closes()?;
522 explicit |= self.explicit;
523 if !explicit {
524 closes = self.trans.get(&key).map_or(0, |m| m.0);
525 }
526 self.trans.insert(key, (closes, next));
527 } else {
528 let m = self.trans.get(&key).copied();
529 match (explicit, m) {
530 (true, Some((_, n))) => {
531 next = n;
532 self.trans.insert(key, (closes, next));
533 }
534 (false, Some((c, n))) => {
535 closes = c;
536 next = n;
537 }
538 (_, None) => bail!("no transition remembered for field {key} at {}", self.p),
539 }
540 }
541 self.close(closes)?;
542 key = self.read_value(next)?;
543 }
544 Ok(())
545 }
546
547 fn store(&mut self, field: u32, child: usize) {
548 let Some(top) = self.stack.last() else { return };
549 let node = top.node;
550 if let Some(Node::Struct(kids)) = self.tree.nodes.get_mut(node) {
551 kids.push((field, child));
552 } else if let Some(Node::List(items)) = self.tree.nodes.get_mut(node) {
553 items.push(child);
554 }
555 }
556
557 fn read_value(&mut self, field: u32) -> Result<u32> {
558 let top_is_array = self.stack.last().is_some_and(|f| f.is_array);
559 let top_field = self.stack.last().map_or(u32::MAX, |f| f.field);
560 if top_is_array && field != top_field {
561 let extra = match self.stack.last().and_then(|f| f.extra) {
563 Some(e) => e,
564 None => {
565 let e = self.push(Node::Struct(Vec::new()))?;
566 if let Some(f) = self.stack.last_mut() {
567 f.extra = Some(e);
568 }
569 e
570 }
571 };
572 let depth = self.stack.len();
573 self.stack.push(Frame {
574 field: top_field,
575 node: extra,
576 is_array: false,
577 left: 0,
578 extra: None,
579 });
580 let r = self.read_value(field);
581 if self.stack.len() == depth + 1 {
583 self.stack.pop();
584 } else if self.stack.len() > depth {
585 self.stack.remove(depth);
586 }
587 return r;
588 }
589 let ty = self.field(field)?.ty;
590 if ty == 0 {
591 let b = self.byte()?;
592 match b {
593 0xe1 => {
594 let n = self.push(Node::Null)?;
595 if let Some(top) = self.stack.last_mut() {
596 if top.is_array {
597 top.left = top.left.saturating_sub(1);
598 }
599 }
600 self.store(field, n);
601 return Ok(field);
602 }
603 0xf8 | 0xf9 if !top_is_array => {
604 let mut n = self.dim()?;
605 if b == 0xf9 {
606 n = n
607 .checked_mul(self.dim()?)
608 .filter(|&x| x <= MAX_ARRAY)
609 .ok_or_else(|| anyhow!("array too large"))?;
610 }
611 let list = self.push(Node::List(Vec::new()))?;
612 self.store(field, list);
613 if n == 0 {
614 return Ok(field);
615 }
616 self.stack.push(Frame {
617 field,
618 node: list,
619 is_array: true,
620 left: n,
621 extra: None,
622 });
623 return Ok(field);
624 }
625 0xfb if top_is_array => {
626 let b2 = self.byte()?;
627 if b2 == 0xe1 {
628 let n = self.push(Node::Null)?;
629 if let Some(top) = self.stack.last_mut() {
630 top.left = top.left.saturating_sub(1);
631 }
632 self.store(field, n);
633 return Ok(field);
634 }
635 if !(b2 == 0xe2 || b2 == 0xe3) {
636 bail!("struct token {b2:02x} at {}", self.p - 1);
637 }
638 }
639 0xe2 | 0xe3 => {}
640 other => bail!("struct token {other:02x} at {}", self.p - 1),
641 }
642 let node = self.push(Node::Struct(Vec::new()))?;
643 if let Some(top) = self.stack.last_mut() {
644 if top.is_array {
645 top.left = top.left.saturating_sub(1);
646 }
647 }
648 self.store(field, node);
649 self.stack.push(Frame {
650 field,
651 node,
652 is_array: false,
653 left: 0,
654 extra: None,
655 });
656 return Ok(field);
657 }
658 let leaf = self.read_leaf(field)?;
659 let n = self.push(leaf)?;
660 self.store(field, n);
661 Ok(field)
662 }
663}
664
665pub mod double {
667 use anyhow::{anyhow, bail, Result};
668
669 use std::f64::consts::PI;
670
671 const GROUP_TOP: [u8; 10] = [0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0];
673
674 fn constant(t: u8) -> Option<f64> {
676 Some(match t {
677 0x03 => 0.125,
678 0x04 => f64::from_bits(0x3FEF_FFFF_FFFF_FFFF),
679 0x0b => 0.06,
680 0x0c => 0.1,
681 0x0d => 0.25,
682 0x0e => 0.5,
683 0x0f => 1.0,
684 0x10 => -1.0,
685 0x11 => PI,
686 0x12 => 0.5 * PI,
687 0x13 => 2.0 * PI,
688 0x14 => 1.5 * PI,
689 0x15 => -PI,
690 0x16 => -0.5 * PI,
691 0x17 => -2.0 * PI,
692 0x18 => 0.0,
693 0x05..=0x0a => f64::NAN, _ => return None,
695 })
696 }
697
698 fn class_top(t: u8) -> Option<u16> {
701 Some(match t {
702 0x4b => 0x3fb0,
703 0x4c => 0x3fb1,
704 0x4d => 0x3fb5,
705 0x4e => 0x3fc0,
706 0x4f..=0x53 => 0x3fc1 + u16::from(t - 0x4f),
707 0x54..=0x57 => 0x3fc7 + u16::from(t - 0x54),
708 0x58 | 0x59 => 0x3fcc + u16::from(t - 0x58),
709 0x5a..=0xa3 => 0x3fcf + u16::from(t - 0x5a),
710 0xa4 => 0xbfc0,
711 0xa5 | 0xa6 => 0xbfd0 + u16::from(t - 0xa5),
712 0xa7..=0xb2 => 0xbfd3 + u16::from(t - 0xa7),
713 0xb3..=0xcf => 0xbfe0 + u16::from(t - 0xb3),
714 0xd0..=0xdc => 0xbffe + u16::from(t - 0xd0),
715 0xdd => 0xc00c,
716 0xde => 0xc010,
717 0xdf => 0xc011,
718 _ => return None,
719 })
720 }
721
722 fn bytes_to_f64(b: [u8; 8]) -> f64 {
723 f64::from_be_bytes(b)
724 }
725
726 pub fn decode(d: &[u8]) -> Result<(f64, usize)> {
728 let &t = d
729 .first()
730 .ok_or_else(|| anyhow!("section ends inside a number"))?;
731 let need = |n: usize| -> Result<&[u8]> {
732 d.get(1..1 + n)
733 .ok_or_else(|| anyhow!("section ends inside a number"))
734 };
735 if let Some(c) = constant(t) {
736 return Ok((c, 1));
737 }
738 match t {
739 0x00..=0x02 => {
740 let n = usize::from(t) + 1;
742 let s = need(n + 1)?;
743 let (&c, low_bytes) = s
744 .split_first()
745 .ok_or_else(|| anyhow!("section ends inside a number"))?;
746 let base = constant(c).unwrap_or(f64::NAN);
747 if base.is_nan() {
748 return Ok((f64::NAN, n + 2));
749 }
750 let mut bits = base.to_bits();
751 let mask = (1u64 << (8 * n)) - 1;
752 let mut low = 0u64;
753 for &x in low_bytes {
754 low = (low << 8) | u64::from(x);
755 }
756 bits = (bits & !mask) | low;
757 Ok((f64::from_bits(bits), n + 2))
758 }
759 0x19..=0x4a => {
760 let g = usize::from((t - 0x19) / 5);
761 let k = (t - 0x19) % 5;
762 let top = GROUP_TOP.get(g).copied().unwrap_or(0x3c);
763 let mut raw = [0u8; 8];
764 raw[0] = top;
765 let used = match k {
766 0 => {
767 raw[1..8].copy_from_slice(need(7)?);
768 7
769 }
770 1 => {
771 let &[a, b] = need(2)? else {
773 bail!("section ends inside a number")
774 };
775 raw = [top, a, b, b, b, b, b, b];
776 2
777 }
778 2 => {
779 let &[a, b] = need(2)? else {
780 bail!("section ends inside a number")
781 };
782 raw = [top, a, b, 0, 0, 0, 0, 0];
783 2
784 }
785 3 => {
786 raw[1..4].copy_from_slice(need(3)?);
787 3
788 }
789 _ => {
790 raw[1..7].copy_from_slice(need(6)?);
791 6
792 }
793 };
794 Ok((bytes_to_f64(raw), 1 + used))
795 }
796 0x4b..=0xdf => {
797 let top = class_top(t).unwrap_or(0x7ff8);
798 let s = need(6)?;
799 let mut raw = [0u8; 8];
800 raw[0..2].copy_from_slice(&top.to_be_bytes());
801 raw[2..8].copy_from_slice(s);
802 Ok((bytes_to_f64(raw), 7))
803 }
804 0xe8..=0xef => {
805 let n = match t {
806 0xe8 => 1,
807 0xe9 => 2,
808 0xea => 3,
809 0xeb => 4,
810 0xec => 7,
811 0xed => 8,
812 0xee => 3,
813 _ => 2,
814 };
815 let s = need(n)?;
816 let mut raw = [0u8; 8];
817 for (r, &x) in raw.iter_mut().zip(s) {
818 *r = x;
819 }
820 Ok((bytes_to_f64(raw), 1 + n))
821 }
822 other => bail!("number token {other:02x}"),
823 }
824 }
825
826 pub fn decode_float(d: &[u8]) -> Result<(f64, usize)> {
829 let &t = d
830 .first()
831 .ok_or_else(|| anyhow!("section ends inside a number"))?;
832 let need = |n: usize| -> Result<&[u8]> {
833 d.get(1..1 + n)
834 .ok_or_else(|| anyhow!("section ends inside a number"))
835 };
836 match t {
837 0x00..=0x32 => Ok((
838 if t == 0 {
839 0.0
840 } else {
841 constant(t).unwrap_or(f64::NAN)
842 },
843 1,
844 )),
845 0x50..=0xb7 | 0xbc..=0xdf => {
846 need(2)?;
847 Ok((f64::NAN, 3))
848 }
849 0xe8..=0xeb => {
850 let n = usize::from(t - 0xe7);
851 let s = need(n)?;
852 let mut raw = [0u8; 4];
853 for (r, &x) in raw.iter_mut().zip(s) {
854 *r = x;
855 }
856 Ok((f64::from(f32::from_be_bytes(raw)), 1 + n))
857 }
858 0x33..=0x4f | 0xb8..=0xbb => {
859 let s = need(3)?;
860 let mut raw = [0u8; 8];
861 if (0x33..=0x4a).contains(&t) {
862 raw[0] = GROUP_TOP
863 .get(usize::from((t - 0x19) / 5))
864 .copied()
865 .unwrap_or(0x3c);
866 raw[1..4].copy_from_slice(s);
867 } else {
868 let top = class_top(t).unwrap_or(0x7ff8);
869 raw[0..2].copy_from_slice(&top.to_be_bytes());
870 raw[2..5].copy_from_slice(s);
871 }
872 Ok((bytes_to_f64(raw), 4))
873 }
874 other => bail!("float token {other:02x}"),
875 }
876 }
877}
878
879#[doc(hidden)]
885pub struct Writer {
886 out: Vec<u8>,
887 fields: Vec<(u8, String)>,
888 pending: usize,
890}
891
892const TY_STRUCT: u8 = 0x00;
894const TY_INT: u8 = 0x01;
895const TY_DOUBLE: u8 = 0x02;
896const TY_STRING: u8 = 0x03;
897
898impl Writer {
899 pub fn new(root: &str) -> Writer {
901 let mut w = Writer {
902 out: Vec::new(),
903 fields: vec![(TY_STRUCT, root.to_string())],
904 pending: 0,
905 };
906 w.out.extend([0xe0, TY_STRUCT]);
907 w.out.extend(root.as_bytes());
908 w.out.extend([0x00, 0xe2]);
909 w
910 }
911
912 fn int_bytes(&mut self, v: i64) {
913 if v < 0 {
914 self.out.push(0xf5);
915 }
916 let a = v.unsigned_abs();
917 if a < 0x80 {
918 self.out.push(a as u8);
919 } else {
920 self.out.push(0xeb);
921 self.out
922 .extend((a.min(i32::MAX as u64) as u32).to_be_bytes());
923 }
924 }
925
926 fn key(&mut self, name: &str, ty: u8) {
928 match self.pending {
929 0 => self.out.push(0xf0),
930 n @ 1..=3 => self.out.push(0xf0 + n as u8),
931 n => {
932 self.out.push(0xf4);
933 self.int_bytes(n as i64);
934 }
935 }
936 self.pending = 0;
937 match self.fields.iter().position(|(t, n)| *t == ty && n == name) {
938 Some(i) => {
939 self.out.push(0xf7);
940 self.int_bytes(i as i64 + 1);
941 }
942 None => {
943 self.fields.push((ty, name.to_string()));
944 self.out.extend([0xe0, ty]);
945 self.out.extend(name.as_bytes());
946 self.out.push(0x00);
947 }
948 }
949 }
950
951 fn dbl_bytes(&mut self, v: f64) {
952 self.out.push(0xed);
953 self.out.extend(v.to_be_bytes());
954 }
955
956 pub fn int(&mut self, name: &str, v: i64) -> &mut Writer {
957 self.key(name, TY_INT);
958 self.int_bytes(v);
959 self
960 }
961
962 pub fn dbl(&mut self, name: &str, v: f64) -> &mut Writer {
963 self.key(name, TY_DOUBLE);
964 self.dbl_bytes(v);
965 self
966 }
967
968 pub fn string(&mut self, name: &str, s: &str) -> &mut Writer {
969 self.key(name, TY_STRING);
970 self.out.extend(s.as_bytes());
971 self.out.push(0x00);
972 self
973 }
974
975 pub fn dbls(&mut self, name: &str, v: &[f64]) -> &mut Writer {
976 self.key(name, TY_DOUBLE);
977 self.out.push(0xf8);
978 self.int_bytes(v.len() as i64);
979 for &x in v {
980 self.dbl_bytes(x);
981 }
982 self
983 }
984
985 pub fn strings(&mut self, name: &str, v: &[&str]) -> &mut Writer {
986 self.key(name, TY_STRING);
987 self.out.push(0xf8);
988 self.int_bytes(v.len() as i64);
989 for s in v {
990 self.out.extend(s.as_bytes());
991 self.out.push(0x00);
992 }
993 self
994 }
995
996 pub fn begin(&mut self, name: &str) -> &mut Writer {
998 self.key(name, TY_STRUCT);
999 self.out.push(0xe2);
1000 self
1001 }
1002
1003 pub fn begin_array(&mut self, name: &str, n: usize) -> &mut Writer {
1007 self.key(name, TY_STRUCT);
1008 self.out.push(0xf8);
1009 self.int_bytes(n as i64);
1010 self
1011 }
1012
1013 pub fn element(&mut self, array: &str) -> &mut Writer {
1014 self.key(array, TY_STRUCT);
1015 self.out.extend([0xfb, 0xe2]);
1016 self
1017 }
1018
1019 pub fn end(&mut self) -> &mut Writer {
1020 self.pending += 1;
1021 self
1022 }
1023
1024 pub fn finish(&self) -> Vec<u8> {
1025 self.out.clone()
1026 }
1027}
1028
1029#[cfg(test)]
1030mod tests {
1031 use super::*;
1032
1033 #[test]
1034 fn the_writer_round_trips_through_the_reader() {
1035 let mut w = Writer::new("top");
1036 w.int("count", 2)
1037 .int("neg", -300)
1038 .dbl("pi", std::f64::consts::PI)
1039 .string("name", "MS_TIP")
1040 .dbls("axis", &[1.0, -0.5, 2.0])
1041 .begin_array("items", 2);
1042 for k in 0..2 {
1043 w.element("items")
1044 .int("id", k)
1045 .dbls("o", &[k as f64; 3])
1046 .end();
1047 }
1048 w.end()
1049 .begin("tail")
1050 .strings("words", &["a", "Offset", "in"])
1051 .end();
1052 let t = parse(&w.finish()).unwrap();
1053 let r = t.root();
1054 assert_eq!(t.int_at(r, "count"), Some(2));
1055 assert_eq!(t.int_at(r, "neg"), Some(-300));
1056 assert_eq!(t.dbl_at(r, "pi"), Some(std::f64::consts::PI));
1057 assert_eq!(t.str_at(r, "name"), Some("MS_TIP"));
1058 assert_eq!(t.dbls(t.child(r, "axis").unwrap()), vec![1.0, -0.5, 2.0]);
1059 let items = t.list(t.child(r, "items").unwrap());
1060 assert_eq!(items.len(), 2);
1061 assert_eq!(t.int_at(items[1], "id"), Some(1));
1062 assert_eq!(t.dbls(t.child(items[1], "o").unwrap()), vec![1.0; 3]);
1063 let tail = t.child(r, "tail").unwrap();
1064 let words: Vec<_> = t
1065 .list(t.child(tail, "words").unwrap())
1066 .iter()
1067 .map(|&i| match t.node(i) {
1068 Node::Str(s) => s.clone(),
1069 _ => String::new(),
1070 })
1071 .collect();
1072 assert_eq!(words, ["a", "Offset", "in"]);
1073 }
1074
1075 fn visib_geom() -> Vec<u8> {
1076 let data = std::fs::read(concat!(
1077 env!("CARGO_MANIFEST_DIR"),
1078 "/tests/fixtures/cad/nist/ctc-01/creo-10/nist_ctc_01_asme1_rd_cr10030.prt.5"
1079 ))
1080 .unwrap();
1081 let toc = super::super::container::toc(&data).unwrap();
1082 super::super::container::section(&data, &toc, "VisibGeom")
1083 .unwrap()
1084 .unwrap()
1085 }
1086
1087 #[test]
1088 fn numbers_decode_like_the_prototype() {
1089 let (v, n) = double::decode(&[0x00, 0x14, 0xd4]).unwrap();
1091 assert_eq!(n, 3);
1092 assert_eq!(v.to_bits(), 0x4012_d97c_7f33_21d4);
1093 let (v, n) = double::decode(&[0x2e, 0x14, 0x33]).unwrap();
1095 assert_eq!(n, 3);
1096 assert!((v - 5.05).abs() < 1e-12, "{v}");
1097 let (v, n) = double::decode(&[0xd8, 0xc5, 0x37, 0x3d, 0x13, 0x16, 0x18]).unwrap();
1099 assert_eq!(n, 7);
1100 assert!((v + 2.8463).abs() < 1e-4, "{v}");
1101 assert_eq!(double::decode(&[0x0f]).unwrap(), (1.0, 1));
1102 assert!(double::decode(&[0xf7]).is_err());
1103 assert!(double::decode(&[0x46, 1]).is_err());
1104 }
1105
1106 #[test]
1107 fn the_visible_geometry_of_ctc_01_parses() {
1108 let sec = visib_geom();
1109 let tree = parse(&sec).unwrap();
1110 let root = tree.root();
1111 let active = tree.child(root, "active_geom").unwrap();
1112 let surfaces = tree.child(active, "srf_array").unwrap();
1113 assert_eq!(tree.list(surfaces).len(), 141);
1114 let curves = tree.child(active, "crv_array").unwrap();
1115 assert_eq!(tree.list(curves).len(), 422);
1116 let first = tree.list(surfaces)[0];
1117 assert_eq!(tree.int_at(first, "geom_id"), Some(106));
1118 assert_eq!(tree.int_at(first, "geom_type"), Some(34));
1119 let prim = tree.child(first, "srf_prim_ptr(plane)").unwrap();
1120 let ls = tree.rows(tree.child(prim, "local_sys").unwrap());
1121 assert_eq!(ls.len(), 4);
1122 assert_eq!(ls[0], [1.0, 0.0, 0.0]);
1123 let body = tree.child(active, "body_array").unwrap();
1124 let b = tree.list(body)[0];
1125 assert_eq!(tree.int_at(b, "body_id"), Some(-5778));
1126 assert_eq!(
1127 tree.str_at(b, "mat_name_ptr"),
1128 Some("PTC_SYSTEM_MTRL_PROPS")
1129 );
1130 }
1131
1132 #[test]
1133 fn cut_and_damaged_sections_are_errors_not_panics() {
1134 let sec = visib_geom();
1135 for cut in (0..sec.len()).step_by(sec.len() / 60) {
1136 let _ = parse(&sec[..cut]);
1137 }
1138 let mut state = 0x9e37_79b9_7f4a_7c15u64;
1139 for _ in 0..30 {
1140 let mut damaged = sec.clone();
1141 for _ in 0..8 {
1142 state ^= state << 13;
1143 state ^= state >> 7;
1144 state ^= state << 17;
1145 let at = (state % damaged.len() as u64) as usize;
1146 damaged[at] = (state >> 32) as u8;
1147 }
1148 let _ = parse(&damaged);
1149 }
1150 }
1151}