1use std::collections::BTreeSet;
5
6use cadmpeg_ir::le::u32_at;
7
8#[derive(Debug, Clone, PartialEq, Eq)]
10pub struct EntityRecord<'a> {
11 pub object_id: Option<u32>,
14 pub object_id_offset: Option<usize>,
16 pub offset: usize,
18 pub bytes: &'a [u8],
20}
21
22#[derive(Debug, Clone, PartialEq, Eq)]
24pub struct TypeDefinition<'a> {
25 pub offset: usize,
27 pub name: &'a str,
29 pub trailing_code: u8,
31 pub registry_suffix: &'a [u8],
33}
34
35#[derive(Debug, Clone, PartialEq, Eq)]
37pub struct FieldDefinition<'a> {
38 pub offset: usize,
40 pub name: &'a str,
42 pub trailing_code: u8,
44 pub registry_suffix: &'a [u8],
46}
47
48#[derive(Debug, Clone, PartialEq, Eq)]
50pub struct StringValue<'a> {
51 pub offset: usize,
53 pub value: &'a str,
55}
56
57#[derive(Debug, Clone, PartialEq, Eq)]
59pub struct SurfacePayloadString<'a> {
60 pub offset: usize,
62 pub value: &'a str,
64}
65
66#[derive(Debug, Clone, PartialEq, Eq)]
68pub struct StoreVersion<'a> {
69 pub offset: usize,
71 pub value: &'a str,
73}
74
75#[derive(Debug, Clone, PartialEq, Eq)]
77pub struct RecordAreaHeader<'a> {
78 pub offset: usize,
80 pub control_words: [u32; 3],
82 pub product: StoreVersion<'a>,
84}
85
86#[derive(Debug, Clone, Copy, PartialEq, Eq)]
88pub enum ReferenceKind {
89 PersistentHandle,
91 Tagged28,
93 RecordOrdinal16,
95}
96
97#[derive(Debug, Clone, Copy, PartialEq, Eq)]
99pub enum CompactIndex {
100 Null,
102 Value(u32),
104}
105
106pub fn compact_indices(bytes: &[u8]) -> Option<Vec<CompactIndex>> {
111 let mut values = Vec::new();
112 let mut at = 0usize;
113 while at < bytes.len() {
114 let (value, width) = compact_index(bytes.get(at..)?)?;
115 at += width;
116 values.push(value);
117 }
118 Some(values)
119}
120
121fn compact_index(bytes: &[u8]) -> Option<(CompactIndex, usize)> {
122 let prefix = *bytes.first()?;
123 if prefix == 0xff {
124 Some((CompactIndex::Null, 1))
125 } else if prefix >= 0x80 {
126 let low = u32::from(*bytes.get(1)?);
127 Some((CompactIndex::Value(u32::from(prefix - 0x80) * 256 + low), 2))
128 } else {
129 Some((CompactIndex::Value(u32::from(prefix)), 1))
130 }
131}
132
133#[derive(Debug, Clone, PartialEq, Eq)]
135pub struct OffsetStoreCountedIndexLane {
136 pub offset: usize,
138 pub declared_count: u8,
140 pub anchor: u32,
142 pub raw_anchor: Vec<u8>,
144 pub anchor_offset: usize,
146 pub members: Vec<(u32, usize)>,
148 pub raw_members: Vec<Vec<u8>>,
150}
151
152#[derive(Debug, Clone, PartialEq, Eq)]
154pub struct OffsetStoreAbrReferenceLane {
155 pub offset: usize,
157 pub slots: Vec<(Option<u32>, usize)>,
159 pub raw_slots: Vec<Vec<u8>>,
161}
162
163#[derive(Debug, Clone, PartialEq, Eq)]
165pub struct OffsetStoreIndexRow {
166 pub offset: usize,
168 pub first_index: u32,
170 pub raw_first_index: Vec<u8>,
172 pub first_index_offset: usize,
174 pub flag: u8,
176 pub indices: [(u32, usize); 4],
178 pub raw_indices: [Vec<u8>; 4],
180}
181
182#[derive(Debug, Clone, PartialEq, Eq)]
184pub struct OffsetStoreLinkedIndexRow {
185 pub offset: usize,
187 pub first_index: (u32, usize),
189 pub raw_first_index: Vec<u8>,
191 pub discriminator: u8,
193 pub target_index: (u32, usize),
195 pub raw_target_index: Vec<u8>,
197 pub indices: [(u32, usize); 3],
199 pub raw_indices: [Vec<u8>; 3],
201 pub flag: u8,
203 pub mode: u8,
205}
206
207#[derive(Debug, Clone, PartialEq, Eq)]
209pub struct OffsetStoreTargetIndexRow {
210 pub offset: usize,
212 pub target_index: (u32, usize),
214 pub raw_target_index: Vec<u8>,
216 pub indices: [(u32, usize); 3],
218 pub raw_indices: [Vec<u8>; 3],
220 pub mode: u8,
222}
223
224pub fn offset_store_index_rows(bytes: &[u8]) -> Vec<OffsetStoreIndexRow> {
226 const PREFIX: [u8; 3] = [0x2d, 0x02, 0x0b];
227 const MIDDLE: [u8; 2] = [0x93, 0x8a];
228 const SUFFIX: [u8; 9] = [0x00, 0x47, 0x04, 0x04, 0x01, 0xc0, 0x44, 0x04, 0x00];
229 let mut rows = Vec::new();
230 for start in 0..bytes.len().saturating_sub(PREFIX.len()) {
231 if bytes.get(start..start + PREFIX.len()) != Some(&PREFIX) {
232 continue;
233 }
234 let first_index_offset = start + PREFIX.len();
235 let Some((CompactIndex::Value(first_index), first_width)) =
236 bytes.get(first_index_offset..).and_then(compact_index)
237 else {
238 continue;
239 };
240 let marker = first_index_offset + first_width;
241 let raw_first_index = bytes[first_index_offset..marker].to_vec();
242 if bytes.get(marker..marker + 2) != Some(&MIDDLE[..2]) {
243 continue;
244 }
245 let Some(flag @ (0x03 | 0x07)) = bytes.get(marker + 2).copied() else {
246 continue;
247 };
248 let mut at = marker + 3;
249 let mut indices = Vec::new();
250 let mut raw_indices = Vec::new();
251 for _ in 0..4 {
252 let Some((CompactIndex::Value(index), width)) = bytes.get(at..).and_then(compact_index)
253 else {
254 indices.clear();
255 break;
256 };
257 indices.push((index, at));
258 raw_indices.push(bytes[at..at + width].to_vec());
259 at += width;
260 }
261 let Ok(indices) = indices.try_into() else {
262 continue;
263 };
264 let Ok(raw_indices) = raw_indices.try_into() else {
265 continue;
266 };
267 if bytes.get(at..at + SUFFIX.len()) != Some(&SUFFIX) {
268 continue;
269 }
270 rows.push(OffsetStoreIndexRow {
271 offset: start,
272 first_index,
273 raw_first_index,
274 first_index_offset,
275 flag,
276 indices,
277 raw_indices,
278 });
279 }
280 rows
281}
282
283pub fn offset_store_linked_index_rows(bytes: &[u8]) -> Vec<OffsetStoreLinkedIndexRow> {
285 const MIDDLE: [u8; 4] = [0xff, 0xff, 0x90, 0xfe];
286 const SUFFIX: [u8; 5] = [0x01, 0xc0, 0x44, 0x04, 0x00];
287 let mut rows = Vec::new();
288 for start in 0..bytes.len().saturating_sub(2) {
289 if bytes.get(start..start + 2) != Some(&[0x02, 0x0b]) {
290 continue;
291 }
292 let first_offset = start + 2;
293 let Some((CompactIndex::Value(first_index), first_width)) =
294 bytes.get(first_offset..).and_then(compact_index)
295 else {
296 continue;
297 };
298 let marker = first_offset + first_width;
299 let raw_first_index = bytes[first_offset..marker].to_vec();
300 if bytes.get(marker..marker + 2) != Some(&[0x93, 0x8c]) {
301 continue;
302 }
303 let Some(discriminator @ (0x16..=0x18)) = bytes.get(marker + 2).copied() else {
304 continue;
305 };
306 let target_offset = marker + 3;
307 let Some((CompactIndex::Value(target_index), target_width)) =
308 bytes.get(target_offset..).and_then(compact_index)
309 else {
310 continue;
311 };
312 let mut at = target_offset + target_width;
313 let raw_target_index = bytes[target_offset..at].to_vec();
314 if bytes.get(at..at + MIDDLE.len()) != Some(&MIDDLE) {
315 continue;
316 }
317 at += MIDDLE.len();
318 let mut indices = Vec::new();
319 let mut raw_indices = Vec::new();
320 for _ in 0..3 {
321 let Some((CompactIndex::Value(index), width)) = bytes.get(at..).and_then(compact_index)
322 else {
323 indices.clear();
324 break;
325 };
326 indices.push((index, at));
327 raw_indices.push(bytes[at..at + width].to_vec());
328 at += width;
329 }
330 let Ok(indices) = indices.try_into() else {
331 continue;
332 };
333 let Ok(raw_indices) = raw_indices.try_into() else {
334 continue;
335 };
336 if bytes.get(at..at + 2) != Some(&[0x00, 0x47]) {
337 continue;
338 }
339 let Some(flag @ (0x03 | 0x07)) = bytes.get(at + 2).copied() else {
340 continue;
341 };
342 let Some(mode @ (0x04 | 0x07)) = bytes.get(at + 3).copied() else {
343 continue;
344 };
345 if bytes.get(at + 4..at + 4 + SUFFIX.len()) != Some(&SUFFIX) {
346 continue;
347 }
348 rows.push(OffsetStoreLinkedIndexRow {
349 offset: start,
350 first_index: (first_index, first_offset),
351 raw_first_index,
352 discriminator,
353 target_index: (target_index, target_offset),
354 raw_target_index,
355 indices,
356 raw_indices,
357 flag,
358 mode,
359 });
360 }
361 rows
362}
363
364pub fn offset_store_target_index_rows(bytes: &[u8]) -> Vec<OffsetStoreTargetIndexRow> {
366 const PREFIX: [u8; 5] = [0x02, 0x01, 0x01, 0x01, 0x16];
367 const MIDDLE: [u8; 4] = [0xff, 0xff, 0x90, 0xfe];
368 const SUFFIX: [u8; 5] = [0x01, 0xc0, 0x44, 0x04, 0x00];
369 let mut rows = Vec::new();
370 for start in 0..bytes.len().saturating_sub(PREFIX.len()) {
371 if bytes.get(start..start + PREFIX.len()) != Some(&PREFIX) {
372 continue;
373 }
374 let target_offset = start + PREFIX.len();
375 let Some((CompactIndex::Value(target_index), target_width)) =
376 bytes.get(target_offset..).and_then(compact_index)
377 else {
378 continue;
379 };
380 let mut at = target_offset + target_width;
381 let raw_target_index = bytes[target_offset..at].to_vec();
382 if bytes.get(at..at + MIDDLE.len()) != Some(&MIDDLE) {
383 continue;
384 }
385 at += MIDDLE.len();
386 let mut indices = Vec::new();
387 let mut raw_indices = Vec::new();
388 for _ in 0..3 {
389 let Some((CompactIndex::Value(index), width)) = bytes.get(at..).and_then(compact_index)
390 else {
391 indices.clear();
392 break;
393 };
394 indices.push((index, at));
395 raw_indices.push(bytes[at..at + width].to_vec());
396 at += width;
397 }
398 let Ok(indices) = indices.try_into() else {
399 continue;
400 };
401 let Ok(raw_indices) = raw_indices.try_into() else {
402 continue;
403 };
404 if bytes.get(at..at + 3) != Some(&[0x00, 0x47, 0x03]) {
405 continue;
406 }
407 let Some(mode @ (0x04 | 0x07)) = bytes.get(at + 3).copied() else {
408 continue;
409 };
410 if bytes.get(at + 4..at + 4 + SUFFIX.len()) != Some(&SUFFIX) {
411 continue;
412 }
413 rows.push(OffsetStoreTargetIndexRow {
414 offset: start,
415 target_index: (target_index, target_offset),
416 raw_target_index,
417 indices,
418 raw_indices,
419 mode,
420 });
421 }
422 rows
423}
424
425pub fn offset_store_abr_reference_lanes(bytes: &[u8]) -> Vec<OffsetStoreAbrReferenceLane> {
427 const SLOT_COUNT: usize = 16;
428 const TERMINATOR: [u8; 7] = [0x02, 0x11, b'A', b'B', b'R', 0xff, 0x03];
429 let mut lanes = Vec::new();
430 for start in 0..bytes.len() {
431 if bytes[start] != 0x11 {
432 continue;
433 }
434 let mut at = start + 1;
435 let mut slots = Vec::with_capacity(SLOT_COUNT);
436 let mut raw_slots = Vec::with_capacity(SLOT_COUNT);
437 for _ in 0..SLOT_COUNT {
438 let Some((value, width)) = bytes.get(at..).and_then(compact_index) else {
439 break;
440 };
441 slots.push((
442 match value {
443 CompactIndex::Null => None,
444 CompactIndex::Value(value) => Some(value),
445 },
446 at,
447 ));
448 raw_slots.push(bytes[at..at + width].to_vec());
449 at += width;
450 }
451 if slots.len() == SLOT_COUNT && bytes.get(at..at + TERMINATOR.len()) == Some(&TERMINATOR) {
452 lanes.push(OffsetStoreAbrReferenceLane {
453 offset: start,
454 slots,
455 raw_slots,
456 });
457 }
458 }
459 lanes
460}
461
462pub fn offset_store_counted_index_lanes(bytes: &[u8]) -> Vec<OffsetStoreCountedIndexLane> {
468 let mut lanes = Vec::new();
469 for start in 0..bytes.len().saturating_sub(4) {
470 if bytes[start] != 0x01 {
471 continue;
472 }
473 let declared_count = bytes[start + 1];
474 if declared_count < 3 {
475 continue;
476 }
477 let mut at = start + 2;
478 let Some((CompactIndex::Value(anchor), width)) = compact_index(&bytes[at..]) else {
479 continue;
480 };
481 let anchor_offset = at;
482 let raw_anchor = bytes[at..at + width].to_vec();
483 at += width;
484 let mut members = Vec::with_capacity(usize::from(declared_count) - 2);
485 let mut raw_members = Vec::with_capacity(usize::from(declared_count) - 2);
486 let mut complete = true;
487 for _ in 0..usize::from(declared_count) - 2 {
488 let Some((CompactIndex::Value(value), width)) = bytes.get(at..).and_then(compact_index)
489 else {
490 complete = false;
491 break;
492 };
493 members.push((value, at));
494 raw_members.push(bytes[at..at + width].to_vec());
495 at += width;
496 }
497 if complete && bytes.get(at..at + 2) == Some(&[0x01, 0x11]) {
498 lanes.push(OffsetStoreCountedIndexLane {
499 offset: start,
500 declared_count,
501 anchor,
502 raw_anchor,
503 anchor_offset,
504 members,
505 raw_members,
506 });
507 }
508 }
509 lanes
510}
511
512#[derive(Debug, Clone, Copy, PartialEq)]
514pub struct ConstructionPayloadScalarField {
515 pub offset: usize,
517 pub field_code: u8,
519 pub value: f64,
521 pub raw_value: [u8; 8],
523}
524
525pub fn construction_payload_scalar_fields(bytes: &[u8]) -> Vec<ConstructionPayloadScalarField> {
527 let mut fields = Vec::new();
528 for start in 0..bytes.len().saturating_sub(12) {
529 if bytes.get(start..start + 3) != Some(b"PYf")
530 || bytes.get(start + 4) != Some(&0x00)
531 || !matches!(bytes.get(start + 5), Some(0x20..=0x3f | 0xa0..=0xbf))
532 {
533 continue;
534 }
535 let Some(raw_value) = bytes
536 .get(start + 5..start + 13)
537 .and_then(|value| <[u8; 8]>::try_from(value).ok())
538 else {
539 continue;
540 };
541 let Some(value) = shifted_ieee_f64(&raw_value) else {
542 continue;
543 };
544 fields.push(ConstructionPayloadScalarField {
545 offset: start,
546 field_code: bytes[start + 3],
547 value,
548 raw_value,
549 });
550 }
551 fields
552}
553
554#[derive(Debug, Clone, PartialEq, Eq)]
556pub struct ConstructionPayloadNamedField<'a> {
557 pub offset: usize,
559 pub type_code: Option<u32>,
561 pub raw_type_code: Option<Vec<u8>>,
563 pub type_code_offset: Option<usize>,
565 pub payload_leading: bool,
567 pub value: &'a str,
569}
570
571#[derive(Debug, Clone, PartialEq)]
573pub struct OffsetStoreNamedPoint {
574 pub name: String,
576 pub values: [f64; 2],
578 pub raw_values: [[u8; 8]; 2],
580 pub value_offsets: [usize; 2],
582 pub block_count: usize,
584}
585
586pub fn offset_store_named_point(blocks: &[&[u8]]) -> Option<OffsetStoreNamedPoint> {
588 let mut bytes = Vec::new();
589 for (block_ordinal, block) in blocks.iter().enumerate() {
590 bytes.extend_from_slice(block);
591 let names = construction_payload_named_fields(&bytes);
592 let [name] = names.as_slice() else {
593 return None;
594 };
595 if !name.payload_leading || parse_positive_decimal_suffix(name.value, "Point").is_none() {
596 return None;
597 }
598 let scalars = construction_payload_scalar_fields(&bytes);
599 match scalars.as_slice() {
600 [] | [_] => {}
601 [first_scalar, second_scalar] => {
602 return Some(OffsetStoreNamedPoint {
603 name: name.value.to_string(),
604 values: [first_scalar.value, second_scalar.value],
605 raw_values: [first_scalar.raw_value, second_scalar.raw_value],
606 value_offsets: [first_scalar.offset, second_scalar.offset],
607 block_count: block_ordinal + 1,
608 });
609 }
610 _ => return None,
611 }
612 }
613 None
614}
615
616fn parse_positive_decimal_suffix(value: &str, prefix: &str) -> Option<u32> {
617 let suffix = value.strip_prefix(prefix)?;
618 if suffix.is_empty() || !suffix.bytes().all(|byte| byte.is_ascii_digit()) {
619 return None;
620 }
621 let ordinal = suffix.parse::<u32>().ok()?;
622 (ordinal != 0).then_some(ordinal)
623}
624
625pub fn construction_payload_named_fields(bytes: &[u8]) -> Vec<ConstructionPayloadNamedField<'_>> {
627 let mut fields = Vec::new();
628 if bytes.first() == Some(&0x03) {
629 if let Some(value) = construction_payload_name_text(bytes, 1) {
630 fields.push(ConstructionPayloadNamedField {
631 offset: 0,
632 type_code: None,
633 raw_type_code: None,
634 type_code_offset: None,
635 payload_leading: true,
636 value,
637 });
638 }
639 }
640 for start in 0..bytes.len().saturating_sub(5) {
641 if bytes[start] != 0x66 {
642 continue;
643 }
644 let Some((CompactIndex::Value(type_code), type_width)) =
645 bytes.get(start + 1..).and_then(compact_index)
646 else {
647 continue;
648 };
649 let marker = start + 1 + type_width;
650 if bytes.get(marker) != Some(&0x03) {
651 continue;
652 }
653 let Some(value) = construction_payload_name_text(bytes, marker + 1) else {
654 continue;
655 };
656 fields.push(ConstructionPayloadNamedField {
657 offset: start,
658 type_code: Some(type_code),
659 raw_type_code: Some(bytes[start + 1..marker].to_vec()),
660 type_code_offset: Some(start + 1),
661 payload_leading: false,
662 value,
663 });
664 }
665 fields
666}
667
668fn construction_payload_name_text(bytes: &[u8], length_offset: usize) -> Option<&str> {
669 let text_len = usize::from(bytes.get(length_offset).copied()?.checked_sub(2)?);
670 let text_start = length_offset.checked_add(1)?;
671 let text_end = text_start.checked_add(text_len)?;
672 let text = bytes.get(text_start..text_end)?;
673 if text.is_empty()
674 || !text.iter().all(u8::is_ascii_graphic)
675 || bytes.get(text_end) != Some(&0x00)
676 {
677 return None;
678 }
679 std::str::from_utf8(text).ok()
680}
681
682#[derive(Debug, Clone, Copy, PartialEq, Eq)]
684pub struct ReferenceValue {
685 pub offset: usize,
687 pub kind: ReferenceKind,
689 pub value: u32,
691}
692
693#[derive(Debug, Clone, Copy, PartialEq, Eq)]
695pub enum ExpressionUnit {
696 Millimeter,
698 Degree,
700}
701
702#[derive(Debug, Clone, PartialEq)]
704pub struct NumericExpression<'a> {
705 pub object_id: Option<u32>,
707 pub offset: usize,
709 pub name: &'a str,
711 pub parameter_index: Option<u32>,
713 pub qualifier: Option<&'a str>,
715 pub unit: ExpressionUnit,
717 pub expression: &'a str,
719 pub value: Option<f64>,
721}
722
723#[derive(Debug, Clone, PartialEq, Eq)]
725pub struct IndexedSection<'a> {
726 pub base: usize,
728 pub entity_index_offset: usize,
730 pub object_id_table_offset: usize,
732 pub types: Vec<TypeDefinition<'a>>,
734 pub fields: Vec<FieldDefinition<'a>>,
736 pub control: Option<EntityRecord<'a>>,
738 pub column_storage: Option<&'a [u8]>,
743 pub records: Vec<EntityRecord<'a>>,
745}
746
747#[derive(Debug, Clone, PartialEq, Eq)]
749pub struct Section<'a> {
750 pub offset: usize,
752 pub byte_len: usize,
754 pub types: Vec<TypeDefinition<'a>>,
756 pub fields: Vec<FieldDefinition<'a>>,
758 pub record_area_offset: Option<usize>,
760 pub record_area: Option<&'a [u8]>,
762}
763
764#[derive(Debug, Clone, Copy, PartialEq, Eq)]
766pub struct OperationLabel<'a> {
767 pub header_offset: usize,
769 pub offset: usize,
771 pub value: &'a str,
773 pub object_indices: [Option<u32>; 4],
775 pub object_index_offsets: [usize; 4],
777}
778
779#[derive(Debug, Clone, Copy, PartialEq, Eq)]
781pub struct OperationRecord<'a> {
782 pub offset: usize,
784 pub bytes: &'a [u8],
786 pub payload_offset: usize,
788 pub payload: &'a [u8],
790 pub label: OperationLabel<'a>,
792}
793
794#[derive(Debug, Clone, Copy, PartialEq, Eq)]
796pub struct OperationPayloadString<'a> {
797 pub offset: usize,
799 pub value: &'a str,
801}
802
803#[derive(Debug, Clone, PartialEq, Eq)]
805pub struct PayloadObjectReference {
806 pub offset: usize,
808 pub object_index: u32,
810 pub raw_object_index: Vec<u8>,
812}
813
814#[derive(Debug, Clone, PartialEq, Eq)]
816pub struct SketchPayloadReferenceField {
817 pub declared_count: u8,
819 pub references: Vec<PayloadObjectReference>,
821}
822
823#[derive(Debug, Clone, PartialEq, Eq)]
825pub struct ProjectedCurvePayloadReferenceField {
826 pub references: Vec<PayloadObjectReference>,
828}
829
830#[derive(Debug, Clone, PartialEq, Eq)]
832pub struct PatternPayloadReferenceField {
833 pub references: Vec<PayloadObjectReference>,
835}
836
837#[derive(Debug, Clone, Copy, PartialEq, Eq)]
839pub enum PatternTransformEncoding {
840 Binary32,
842 Binary64,
844}
845
846#[derive(Debug, Clone, PartialEq)]
848pub struct PatternPayloadTransformLane {
849 pub offset: usize,
851 pub declared_count: u8,
853 pub encoding: PatternTransformEncoding,
855 pub values: Vec<f64>,
857 pub value_offsets: Vec<usize>,
859 pub raw_values: Vec<Vec<u8>>,
861 pub selectors: Vec<u32>,
863 pub raw_selectors: Vec<Vec<u8>>,
865 pub selector_offsets: Vec<usize>,
867}
868
869#[derive(Debug, Clone, PartialEq, Eq)]
871pub struct PointFeaturePayloadHeader {
872 pub reference: PayloadObjectReference,
874 pub mode: u8,
876}
877
878#[derive(Debug, Clone, Copy, PartialEq)]
880pub struct PointFeatureScalarLane {
881 pub values: [f64; 6],
883 pub raw_values: [[u8; 8]; 6],
885 pub value_offsets: [usize; 6],
887}
888
889#[derive(Debug, Clone, PartialEq, Eq)]
891pub struct DraftFeaturePayloadReferenceField {
892 pub references: [PayloadObjectReference; 4],
894}
895
896#[derive(Debug, Clone, PartialEq, Eq)]
898pub struct DraftFeatureLeadingIndexLane {
899 pub declared_count: u8,
901 pub indices: Vec<(u32, usize)>,
903 pub raw_indices: Vec<Vec<u8>>,
905}
906
907#[derive(Debug, Clone, PartialEq, Eq)]
909pub struct DraftFeatureTerminalLane {
910 pub indices: [u32; 2],
912 pub raw_indices: [[u8; 2]; 2],
914 pub index_offsets: [usize; 2],
916 pub tail: [u8; 3],
918 pub offset: usize,
920}
921
922#[derive(Debug, Clone, PartialEq, Eq)]
924pub struct SurfaceFeaturePayloadReferenceField {
925 pub references: [PayloadObjectReference; 14],
927}
928
929#[derive(Debug, Clone, PartialEq, Eq)]
931pub struct SurfaceFeaturePayloadBranch {
932 pub offset: usize,
934 pub mode: u8,
936 pub declared_count: u8,
938 pub witnessed: bool,
940 pub members: Vec<PayloadObjectReference>,
942 pub terminal: PayloadObjectReference,
944 pub suffix: Vec<u8>,
946}
947
948#[derive(Debug, Clone, PartialEq, Eq)]
950pub struct SurfaceFeaturePayloadBranches {
951 pub family: u8,
953 pub header_code: u8,
955 pub branches: Vec<SurfaceFeaturePayloadBranch>,
957}
958
959#[derive(Debug, Clone, PartialEq, Eq)]
961pub struct ExtrudeProfileReferenceField {
962 pub references: Vec<PayloadObjectReference>,
964 pub witnessed: bool,
966}
967
968#[derive(Debug, Clone, PartialEq, Eq)]
970pub struct DatumCsysReferenceField {
971 pub control: u8,
973 pub references: [PayloadObjectReference; 8],
975}
976
977#[derive(Debug, Clone, Copy, PartialEq, Eq)]
979pub struct DatumPlanePayloadHeader {
980 pub control: u8,
982 pub declared_count: u8,
984 pub branch_tag: u8,
986}
987
988#[derive(Debug, Clone, PartialEq, Eq)]
990pub struct DatumPlaneSingleReferenceBranch {
991 pub descriptor_index: u32,
993 pub raw_descriptor_index: Vec<u8>,
995 pub descriptor_offset: usize,
997 pub object_index: u32,
999 pub raw_object_index: Vec<u8>,
1001 pub object_offset: usize,
1003}
1004
1005#[derive(Debug, Clone, PartialEq, Eq)]
1007pub struct DatumPlaneDoubleReferenceBranch {
1008 pub references: [PayloadObjectReference; 2],
1010}
1011
1012#[derive(Debug, Clone, PartialEq, Eq)]
1014pub struct DatumPlaneObjectIndexLane {
1015 pub offset: usize,
1017 pub declared_count: u8,
1019 pub indices: Vec<(u32, usize)>,
1021 pub raw_indices: Vec<Vec<u8>>,
1023 pub trailer: u32,
1025}
1026
1027#[derive(Debug, Clone, Copy, PartialEq)]
1029pub struct DatumPlaneObjectScalarPair {
1030 pub offset: usize,
1032 pub values: [f64; 2],
1034 pub raw_values: [[u8; 8]; 2],
1036 pub value_offsets: [usize; 2],
1038}
1039
1040#[derive(Debug, Clone, PartialEq, Eq)]
1042pub struct DatumPlaneDescriptorBlock {
1043 pub identity: String,
1045 pub suffix: Vec<u8>,
1047 pub schema_index: u32,
1049 pub label: String,
1051}
1052
1053#[derive(Debug, Clone, PartialEq)]
1055pub struct ObjectPayloadScalarPair {
1056 pub offset: usize,
1058 pub values: [f64; 2],
1060 pub raw_values: [[u8; 8]; 2],
1062 pub value_offsets: [usize; 2],
1064 pub discriminator: Vec<u8>,
1066}
1067
1068#[derive(Debug, Clone, PartialEq)]
1070pub struct SketchPayloadFixedPair {
1071 pub offset: usize,
1073 pub values: [f64; 2],
1075 pub value_offsets: [usize; 2],
1077 pub raw_values: [[u8; 7]; 2],
1079}
1080
1081#[derive(Debug, Clone, PartialEq)]
1083pub struct DatumCsysPayloadFixedPair {
1084 pub offset: usize,
1086 pub values: [f64; 2],
1088 pub value_offsets: [usize; 2],
1090 pub raw_values: [[u8; 7]; 2],
1092 pub discriminator: Vec<u8>,
1094}
1095
1096#[derive(Debug, Clone, PartialEq, Eq)]
1098pub struct DatumCsysDescriptorBlock {
1099 pub prefix: Vec<u8>,
1101 pub identity: String,
1103 pub suffix: Vec<u8>,
1105 pub identity_offset: usize,
1107}
1108
1109#[derive(Debug, Clone, PartialEq, Eq)]
1111pub struct DraftConstructionIdentityFrame {
1112 pub offset: usize,
1114 pub prefix: Vec<u8>,
1116 pub form: DraftConstructionIdentityFrameForm,
1118 pub identity: String,
1120 pub identity_offset: usize,
1122}
1123
1124#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1126pub enum DraftConstructionIdentityFrameForm {
1127 IndexedBranch {
1129 first_index: u32,
1131 second_index: Option<u32>,
1133 branch: u8,
1135 },
1136 Tagged {
1138 index: Option<u32>,
1140 },
1141}
1142
1143#[derive(Debug, Clone, PartialEq)]
1145pub struct DraftConstructionFixedLane {
1146 pub offset: usize,
1148 pub values: Vec<f64>,
1150 pub markers: Vec<u8>,
1152 pub raw_values: Vec<[u8; 7]>,
1154 pub value_offsets: Vec<usize>,
1156}
1157
1158#[derive(Debug, Clone, PartialEq)]
1160pub struct DraftConstructionBinary32Lane {
1161 pub offset: usize,
1163 pub discriminator: [u8; 18],
1165 pub branch: u8,
1167 pub values: Vec<f64>,
1169 pub raw_values: Vec<[u8; 4]>,
1171 pub value_offsets: Vec<usize>,
1173}
1174
1175#[derive(Debug, Clone, PartialEq, Eq)]
1177pub struct DataBlockObjectFrame {
1178 pub object_id: u32,
1180 pub raw_object_id: Vec<u8>,
1182 pub offset: usize,
1184}
1185
1186#[derive(Debug, Clone, Copy, PartialEq)]
1188pub struct ExtrudePayloadHeader {
1189 pub offset: usize,
1191 pub scalars: [f64; 2],
1193 pub raw_scalars: [[u8; 8]; 2],
1195}
1196
1197#[derive(Debug, Clone, PartialEq, Eq)]
1199pub struct ExtrudePayloadFooter {
1200 pub offset: usize,
1202 pub type_indices: [u32; 2],
1204 pub raw_type_indices: [Vec<u8>; 2],
1206 pub type_index_offsets: [usize; 2],
1208 pub mode_indices: [u32; 2],
1210 pub flags: [u8; 4],
1212 pub trailing_indices: Vec<u32>,
1214 pub raw_trailing_indices: Vec<Vec<u8>>,
1216 pub trailing_index_offsets: Vec<usize>,
1218}
1219
1220#[derive(Debug, Clone, PartialEq)]
1222pub struct SimpleHoleRepeatedScalarLane {
1223 pub values: Vec<f64>,
1225 pub raw_values: Vec<[u8; 8]>,
1227 pub witness_offsets: [Vec<usize>; 2],
1229}
1230
1231#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1233pub struct SimpleHoleRepeatedScalarLaneBlockReferences {
1234 pub first: [u32; 2],
1236 pub second: [u32; 2],
1238 pub offsets: [[usize; 2]; 2],
1240}
1241
1242#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1244pub enum PayloadScalarEncoding {
1245 Zero,
1247 Binary32,
1249 Binary64,
1251}
1252
1253#[derive(Debug, Clone, PartialEq)]
1255pub struct PayloadScalar {
1256 pub offset: usize,
1258 pub value: f64,
1260 pub encoding: PayloadScalarEncoding,
1262 pub raw_value: Vec<u8>,
1264}
1265
1266#[derive(Debug, Clone, PartialEq)]
1268pub struct OperationBodyScalarTriple {
1269 pub body_reference_ordinal: u32,
1271 pub body_object_index: u32,
1273 pub branch: u8,
1275 pub scalars: [PayloadScalar; 3],
1277}
1278
1279#[derive(Debug, Clone, PartialEq, Eq)]
1281pub struct OperationBodyMember {
1282 pub body_reference_ordinal: u32,
1284 pub body_object_index: u32,
1286 pub ordinal: u32,
1288 pub member_index: u32,
1290 pub raw_member_index: Vec<u8>,
1292 pub offset: usize,
1294}
1295
1296#[derive(Debug, Clone, PartialEq, Eq)]
1298pub struct OperationBody11Continuation {
1299 pub body_reference_ordinal: u32,
1301 pub body_object_index: u32,
1303 pub continuation_index: u32,
1305 pub raw_continuation_index: Vec<u8>,
1307 pub continuation_offset: usize,
1309 pub terminal_object_index: u32,
1311 pub raw_terminal_object_index: Vec<u8>,
1313 pub terminal_offset: usize,
1315}
1316
1317#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1319pub enum OperationBodyReferenceLaneEncoding {
1320 CompactIndex,
1322 PayloadObjectIndex,
1324}
1325
1326#[derive(Debug, Clone, PartialEq, Eq)]
1328pub struct OperationBodyReferenceLaneValue {
1329 pub ordinal: u32,
1331 pub object_index: u32,
1333 pub raw_value: Vec<u8>,
1335 pub offset: usize,
1337}
1338
1339#[derive(Debug, Clone, PartialEq, Eq)]
1341pub struct OperationBodyReferenceLane {
1342 pub body_reference_ordinal: u32,
1344 pub body_object_index: u32,
1346 pub branch: u8,
1348 pub encoding: OperationBodyReferenceLaneEncoding,
1350 pub values: Vec<OperationBodyReferenceLaneValue>,
1352}
1353
1354#[derive(Debug, Clone, PartialEq)]
1356pub struct ExtrudePayload32Branch {
1357 pub offset: usize,
1359 pub body_object_index: u32,
1361 pub scalar: f64,
1363 pub raw_scalar: [u8; 8],
1365 pub atoms_be: Vec<u32>,
1367 pub atom_offsets: Vec<usize>,
1369 pub atom_indices: Vec<u32>,
1371 pub first_indices: Vec<u32>,
1373 pub raw_first_indices: Vec<Vec<u8>>,
1375 pub first_index_offsets: Vec<usize>,
1377 pub second_indices: Vec<u32>,
1379 pub raw_second_indices: Vec<Vec<u8>>,
1381 pub second_index_offsets: Vec<usize>,
1383 pub terminal_object_index: u32,
1385 pub raw_terminal_object_index: Vec<u8>,
1387 pub terminal_offset: usize,
1389}
1390
1391#[derive(Debug, Clone, PartialEq, Eq)]
1393pub struct BlockConstructionReferenceField {
1394 pub control: u8,
1396 pub references: Vec<PayloadObjectReference>,
1398}
1399
1400#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1402pub struct ExpressionDeclarationName<'a> {
1403 pub offset: usize,
1405 pub value: &'a str,
1407 pub parameter_index: u32,
1409 pub qualifier: Option<&'a str>,
1411 pub literal: Option<&'a str>,
1413}
1414
1415#[derive(Debug, Clone, PartialEq, Eq)]
1417pub struct OperationBodyReference {
1418 pub offset: usize,
1420 pub object_index: u32,
1422 pub raw_object_index: Vec<u8>,
1424}
1425
1426#[derive(Debug, Clone, PartialEq, Eq)]
1428pub struct DataBlockObjectReference {
1429 pub offset: usize,
1431 pub object_index: u32,
1433 pub raw_object_index: Vec<u8>,
1435}
1436
1437#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1439pub enum BooleanOperationKind {
1440 Unite,
1442 Subtract,
1444 Intersect,
1446}
1447
1448#[derive(Debug, Clone, PartialEq, Eq)]
1450pub struct BooleanOperation {
1451 pub offset: usize,
1453 pub kind: BooleanOperationKind,
1455 pub target: u32,
1457 pub raw_target: Vec<u8>,
1459 pub target_offset: usize,
1461 pub tools: Vec<u32>,
1463 pub raw_tools: Vec<Vec<u8>>,
1465 pub tool_offsets: Vec<usize>,
1467}
1468
1469impl<'a> IndexedSection<'a> {
1470 pub const fn base_offset(&self) -> usize {
1472 self.base
1473 }
1474
1475 pub fn numeric_expressions(&self) -> Vec<NumericExpression<'a>> {
1477 self.numeric_expression_records()
1478 .into_iter()
1479 .map(|(_, expression)| expression)
1480 .collect()
1481 }
1482
1483 pub fn numeric_expression_records(&self) -> Vec<(usize, NumericExpression<'a>)> {
1485 if !self.records.iter().any(|record| {
1486 record
1487 .bytes
1488 .windows(b"hostglobalvariables".len())
1489 .any(|window| window == b"hostglobalvariables")
1490 }) {
1491 return Vec::new();
1492 }
1493 self.records
1494 .iter()
1495 .enumerate()
1496 .filter_map(|(record_ordinal, record)| {
1497 numeric_expression_at(record.bytes, record.offset, record.object_id)
1498 .map(|expression| (record_ordinal, expression))
1499 })
1500 .collect()
1501 }
1502
1503 pub fn string_values(&self) -> Vec<(usize, usize, Option<u32>, StringValue<'a>)> {
1505 self.records
1506 .iter()
1507 .enumerate()
1508 .flat_map(|(record_ordinal, record)| {
1509 string_values(record.bytes, record.offset)
1510 .into_iter()
1511 .enumerate()
1512 .map(move |(value_ordinal, value)| {
1513 (record_ordinal, value_ordinal, record.object_id, value)
1514 })
1515 })
1516 .collect()
1517 }
1518
1519 pub fn references(&self) -> Vec<(usize, usize, Option<u32>, ReferenceValue)> {
1521 self.records
1522 .iter()
1523 .enumerate()
1524 .flat_map(|(record_ordinal, record)| {
1525 let mut references = record_references(record.bytes, record.offset);
1526 references.extend(counted_record_references(
1527 record.bytes,
1528 record.offset,
1529 self.records.len(),
1530 ));
1531 references.sort_by_key(|reference| reference.offset);
1532 references
1533 .into_iter()
1534 .enumerate()
1535 .map(move |(reference_ordinal, reference)| {
1536 (
1537 record_ordinal,
1538 reference_ordinal,
1539 record.object_id,
1540 reference,
1541 )
1542 })
1543 })
1544 .collect()
1545 }
1546}
1547
1548impl<'a> Section<'a> {
1549 pub fn record_area_header(&self) -> Option<RecordAreaHeader<'a>> {
1551 let bytes = self.record_area?;
1552 let offset = self.record_area_offset?;
1553 let control_words = [u32_at(bytes, 0)?, u32_at(bytes, 4)?, u32_at(bytes, 8)?];
1554 let suffix = bytes.get(12..)?;
1555 is_product_record(suffix).then_some(())?;
1556 let length = usize::from(suffix[2]) - 2;
1557 Some(RecordAreaHeader {
1558 offset,
1559 control_words,
1560 product: StoreVersion {
1561 offset: offset + 12,
1562 value: std::str::from_utf8(&suffix[3..3 + length]).ok()?,
1563 },
1564 })
1565 }
1566
1567 pub fn operation_labels(&self) -> Vec<OperationLabel<'a>> {
1569 let Some(bytes) = self.record_area else {
1570 return Vec::new();
1571 };
1572 let Some(base_offset) = self.record_area_offset else {
1573 return Vec::new();
1574 };
1575 operation_labels(bytes, base_offset)
1576 }
1577
1578 pub fn boolean_operations(&self) -> Vec<BooleanOperation> {
1580 let Some(bytes) = self.record_area else {
1581 return Vec::new();
1582 };
1583 let Some(base_offset) = self.record_area_offset else {
1584 return Vec::new();
1585 };
1586 boolean_operations(bytes, base_offset)
1587 }
1588
1589 pub fn operation_records(&self) -> Vec<OperationRecord<'a>> {
1591 let Some(bytes) = self.record_area else {
1592 return Vec::new();
1593 };
1594 let Some(base_offset) = self.record_area_offset else {
1595 return Vec::new();
1596 };
1597 operation_records(bytes, base_offset)
1598 }
1599
1600 pub fn operation_records_with_label_ordinals(&self) -> Vec<(usize, OperationRecord<'a>)> {
1602 let labels = self.operation_labels();
1603 self.operation_records()
1604 .into_iter()
1605 .filter_map(|record| {
1606 labels
1607 .iter()
1608 .position(|label| label.offset == record.label.offset)
1609 .map(|ordinal| (ordinal, record))
1610 })
1611 .collect()
1612 }
1613
1614 pub fn operation_body_references(&self) -> Vec<(usize, OperationBodyReference)> {
1616 self.operation_records_with_label_ordinals()
1617 .into_iter()
1618 .filter_map(|(ordinal, record)| {
1619 operation_body_reference(record).map(|reference| (ordinal, reference))
1620 })
1621 .collect()
1622 }
1623}
1624
1625pub fn operation_labels(bytes: &[u8], base_offset: usize) -> Vec<OperationLabel<'_>> {
1627 const HEADER: &[u8] = &[
1628 0x80, 0xcd, 0x01, 0x04, 0x01, 0x2f, 0xa4, 0x7a, 0xe1, 0x47, 0xae, 0x14, 0x7b, 0xff, 0xff,
1629 ];
1630 let mut labels = Vec::new();
1631 for marker in bytes
1632 .windows(HEADER.len())
1633 .enumerate()
1634 .filter_map(|(offset, window)| (window == HEADER).then_some(offset))
1635 {
1636 let mut at = marker + HEADER.len();
1637 let mut object_indices = [None; 4];
1638 let mut object_index_offsets = [0; 4];
1639 let mut valid = true;
1640 for (slot, offset) in object_indices
1641 .iter_mut()
1642 .zip(object_index_offsets.iter_mut())
1643 {
1644 *offset = base_offset + at;
1645 let Some((value, next)) = feature_object_index(bytes, at) else {
1646 valid = false;
1647 break;
1648 };
1649 *slot = value;
1650 at = next;
1651 }
1652 if !valid || bytes.get(at) != Some(&0x03) {
1653 continue;
1654 }
1655 let Some(length) = bytes.get(at + 1).copied().map(usize::from) else {
1656 continue;
1657 };
1658 if length < 3 {
1659 continue;
1660 }
1661 let Some(end) = at.checked_add(length) else {
1662 continue;
1663 };
1664 if bytes.get(end) != Some(&0) {
1665 continue;
1666 }
1667 let Some(name) = bytes.get(at + 2..end) else {
1668 continue;
1669 };
1670 if !name
1671 .iter()
1672 .all(|byte| byte.is_ascii_graphic() || *byte == b' ')
1673 {
1674 continue;
1675 }
1676 let Ok(value) = std::str::from_utf8(name) else {
1677 continue;
1678 };
1679 labels.push(OperationLabel {
1680 header_offset: base_offset + marker,
1681 offset: base_offset + at,
1682 value,
1683 object_indices,
1684 object_index_offsets,
1685 });
1686 }
1687 labels
1688}
1689
1690pub fn operation_records(bytes: &[u8], base_offset: usize) -> Vec<OperationRecord<'_>> {
1692 let labels = operation_labels(bytes, base_offset);
1693 labels
1694 .iter()
1695 .enumerate()
1696 .filter_map(|(ordinal, label)| {
1697 let start = label.header_offset.checked_sub(base_offset)?;
1698 let end = labels
1699 .get(ordinal + 1)
1700 .map_or(bytes.len(), |next| next.header_offset - base_offset);
1701 let label_at = label.offset.checked_sub(base_offset)?;
1702 let payload_start = label_at
1703 .checked_add(usize::from(*bytes.get(label_at + 1)?))?
1704 .checked_add(1)?;
1705 Some(OperationRecord {
1706 offset: label.header_offset,
1707 bytes: bytes.get(start..end)?,
1708 payload_offset: base_offset + payload_start,
1709 payload: bytes.get(payload_start..end)?,
1710 label: *label,
1711 })
1712 })
1713 .collect()
1714}
1715
1716pub fn operation_payload_strings(record: OperationRecord<'_>) -> Vec<OperationPayloadString<'_>> {
1718 let mut strings = Vec::new();
1719 let mut at = 0usize;
1720 while at + 4 <= record.payload.len() {
1721 if record.payload[at] != 0x04 {
1722 at += 1;
1723 continue;
1724 }
1725 let declared = usize::from(record.payload[at + 1]);
1726 let Some(end) = at.checked_add(declared) else {
1727 at += 1;
1728 continue;
1729 };
1730 let Some(raw) = record.payload.get(at + 2..end) else {
1731 at += 1;
1732 continue;
1733 };
1734 let Some(value) = std::str::from_utf8(raw).ok().filter(|value| {
1735 !value.is_empty() && value.chars().all(|character| !character.is_control())
1736 }) else {
1737 at += 1;
1738 continue;
1739 };
1740 if declared < 3 || record.payload.get(end) != Some(&0) {
1741 at += 1;
1742 continue;
1743 }
1744 strings.push(OperationPayloadString {
1745 offset: record.payload_offset + at,
1746 value,
1747 });
1748 at = end + 1;
1749 }
1750 strings
1751}
1752
1753pub fn simple_hole_repeated_scalar_lane(
1755 record: OperationRecord<'_>,
1756) -> Option<SimpleHoleRepeatedScalarLane> {
1757 if record.label.value != "SIMPLE HOLE" {
1758 return None;
1759 }
1760 let templates = operation_payload_strings(record)
1761 .into_iter()
1762 .filter(|value| value.value.starts_with("Hole_"))
1763 .collect::<Vec<_>>();
1764 let [template] = templates.as_slice() else {
1765 return None;
1766 };
1767 let boundary = template.offset.checked_sub(record.payload_offset)?;
1768 let prefix = record.payload.get(..boundary)?;
1769 let mut scalars = Vec::new();
1770 let mut at = 0usize;
1771 while at + 8 <= prefix.len() {
1772 if prefix[at] == 0x30 {
1773 let raw_value = <[u8; 8]>::try_from(&prefix[at..at + 8]).ok()?;
1774 if let Some(value) = shifted_ieee_f64(&raw_value) {
1775 scalars.push((raw_value, value, record.payload_offset + at));
1776 at += 8;
1777 continue;
1778 }
1779 }
1780 at += 1;
1781 }
1782 let half = scalars.len().checked_div(2)?;
1783 if half == 0 || scalars.len() != half * 2 {
1784 return None;
1785 }
1786 let (first, second) = scalars.split_at(half);
1787 if first
1788 .iter()
1789 .zip(second)
1790 .any(|(left, right)| left.0 != right.0)
1791 {
1792 return None;
1793 }
1794 Some(SimpleHoleRepeatedScalarLane {
1795 values: first.iter().map(|scalar| scalar.1).collect(),
1796 raw_values: first.iter().map(|scalar| scalar.0).collect(),
1797 witness_offsets: [
1798 first.iter().map(|scalar| scalar.2).collect(),
1799 second.iter().map(|scalar| scalar.2).collect(),
1800 ],
1801 })
1802}
1803
1804pub fn simple_hole_repeated_scalar_lane_block_references(
1807 record: OperationRecord<'_>,
1808) -> Option<SimpleHoleRepeatedScalarLaneBlockReferences> {
1809 let pair = simple_hole_repeated_scalar_lane(record)?;
1810 let decode_pair = |coordinate_offset: usize| {
1811 let relative = coordinate_offset.checked_sub(record.payload_offset)?;
1812 let mut at = relative.checked_add(8)?;
1813 let first_offset = at;
1814 let (first, width) = payload_object_index(record.payload.get(at..)?)?;
1815 at += width;
1816 let second_offset = at;
1817 let (second, _) = payload_object_index(record.payload.get(at..)?)?;
1818 Some((
1819 [first, second],
1820 [
1821 record.payload_offset + first_offset,
1822 record.payload_offset + second_offset,
1823 ],
1824 ))
1825 };
1826 let (first, first_offsets) = decode_pair(*pair.witness_offsets[0].last()?)?;
1827 let (second, second_offsets) = decode_pair(*pair.witness_offsets[1].last()?)?;
1828 Some(SimpleHoleRepeatedScalarLaneBlockReferences {
1829 first,
1830 second,
1831 offsets: [first_offsets, second_offsets],
1832 })
1833}
1834
1835pub fn sketch_payload_references(
1837 record: OperationRecord<'_>,
1838) -> Option<SketchPayloadReferenceField> {
1839 if record.label.value != "SKETCH" {
1840 return None;
1841 }
1842 let mut matches = Vec::new();
1843 for start in 0..record.payload.len().saturating_sub(3) {
1844 if record.payload.get(start..start + 2) != Some(&[0x01, 0x00]) {
1845 continue;
1846 }
1847 if let Some(references) = sketch_reference_field(record, start) {
1848 matches.push(references);
1849 }
1850 }
1851 let [references] = matches.as_slice() else {
1852 return None;
1853 };
1854 Some(references.clone())
1855}
1856
1857fn sketch_reference_field(
1858 record: OperationRecord<'_>,
1859 start: usize,
1860) -> Option<SketchPayloadReferenceField> {
1861 let flag = *record.payload.get(start + 2)?;
1862 let (declared_count, mut at) = match flag {
1863 0 => (0, start + 3),
1864 1 => {
1865 let count = *record.payload.get(start + 3)?;
1866 if count == 0 {
1867 return None;
1868 }
1869 (count, start + 4)
1870 }
1871 _ => return None,
1872 };
1873 let leading_count = declared_count.saturating_sub(1) as usize;
1874 let mut references = Vec::with_capacity(leading_count + 1);
1875 for _ in 0..leading_count {
1876 let (object_index, width) = payload_object_index(record.payload.get(at..)?)?;
1877 references.push(PayloadObjectReference {
1878 offset: record.payload_offset + at,
1879 object_index,
1880 raw_object_index: record.payload[at..at + width].to_vec(),
1881 });
1882 at += width;
1883 }
1884 if record.payload.get(at..at + 2) != Some(&[0x00, 0x00]) {
1885 return None;
1886 }
1887 at += 2;
1888 let (object_index, width) = payload_object_index(record.payload.get(at..)?)?;
1889 references.push(PayloadObjectReference {
1890 offset: record.payload_offset + at,
1891 object_index,
1892 raw_object_index: record.payload[at..at + width].to_vec(),
1893 });
1894 at += width;
1895 if record.payload.get(at..at + 4) != Some(&[0x01, 0x00, 0x00, 0x00]) {
1896 return None;
1897 }
1898 Some(SketchPayloadReferenceField {
1899 declared_count,
1900 references,
1901 })
1902}
1903
1904fn payload_object_index(bytes: &[u8]) -> Option<(u32, usize)> {
1905 match *bytes.first()? {
1906 0xf0 => Some((u32::from(*bytes.get(1)?), 2)),
1907 0xf1 => {
1908 let value = u16::from_be_bytes([*bytes.get(1)?, *bytes.get(2)?]);
1909 (value >= 0x0100).then_some((u32::from(value), 3))
1910 }
1911 _ => None,
1912 }
1913}
1914
1915pub fn projected_curve_payload_references(
1918 record: OperationRecord<'_>,
1919) -> Option<ProjectedCurvePayloadReferenceField> {
1920 const CPROJ_MIDDLE: [u8; 5] = [0x80, 0x57, 0x00, 0x02, 0x01];
1921 const CPROJ_SUFFIX: [u8; 5] = [0xff, 0x01, 0x02, 0x02, 0x7d];
1922 const CMB_PREFIX: [u8; 10] = [0x3c, 0x32, 0x01, 0x02, 0x32, 0x01, 0x04, 0x36, 0x01, 0x33];
1923 const CMB_BRANCH_PREFIX: [u8; 3] = [0x16, 0x01, 0x02];
1924 const CMB_BRANCH_MIDDLE: [u8; 7] = [0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00];
1925 const CMB_BRANCH_SUFFIX: [u8; 3] = [0x00, 0x81, 0x5c];
1926 const CMB_TAIL_PREFIX: [u8; 4] = [0xff, 0x01, 0xff, 0x01];
1927 const CMB_TAIL_SUFFIX: [u8; 2] = [0x04, 0x02];
1928 let decode_reference = |at: &mut usize| {
1929 let offset = *at;
1930 let (object_index, width) = payload_object_index(record.payload.get(offset..)?)?;
1931 *at += width;
1932 Some(PayloadObjectReference {
1933 offset: record.payload_offset + offset,
1934 object_index,
1935 raw_object_index: record.payload[offset..offset + width].to_vec(),
1936 })
1937 };
1938 let decode_field = |start: usize| match record.label.value {
1939 "CPROJ" => {
1940 let mut at = start + 2;
1941 let mut references = Vec::with_capacity(3);
1942 references.push(decode_reference(&mut at)?);
1943 references.push(decode_reference(&mut at)?);
1944 (record.payload.get(at..at + CPROJ_MIDDLE.len()) == Some(&CPROJ_MIDDLE))
1945 .then_some(())?;
1946 at += CPROJ_MIDDLE.len();
1947 references.push(decode_reference(&mut at)?);
1948 (record.payload.get(at..at + CPROJ_SUFFIX.len()) == Some(&CPROJ_SUFFIX))
1949 .then_some(())?;
1950 Some(ProjectedCurvePayloadReferenceField { references })
1951 }
1952 "CPROJ_CMB" => {
1953 let mut at = start + CMB_PREFIX.len();
1954 let mut references = Vec::with_capacity(8);
1955 references.push(decode_reference(&mut at)?);
1956 (record.payload.get(at) == Some(&0x33)).then_some(())?;
1957 at += 1;
1958 references.push(decode_reference(&mut at)?);
1959 (record.payload.get(at) == Some(&0x00)).then_some(())?;
1960 at += 1;
1961 references.push(decode_reference(&mut at)?);
1962 (record.payload.get(at..at + 6) == Some(&[0; 6])).then_some(())?;
1963 at += 6;
1964 references.push(decode_reference(&mut at)?);
1965 for anchor in 0..2 {
1966 (record.payload.get(at..at + CMB_BRANCH_PREFIX.len()) == Some(&CMB_BRANCH_PREFIX))
1967 .then_some(())?;
1968 at += CMB_BRANCH_PREFIX.len();
1969 let repeated = decode_reference(&mut at)?;
1970 (repeated.object_index == references[anchor].object_index).then_some(())?;
1971 (record.payload.get(at..at + CMB_BRANCH_MIDDLE.len()) == Some(&CMB_BRANCH_MIDDLE))
1972 .then_some(())?;
1973 at += CMB_BRANCH_MIDDLE.len();
1974 (record.payload.get(at..at + 3) == Some(&[0xff, 0x01, 0x02])).then_some(())?;
1975 at += 3;
1976 references.push(decode_reference(&mut at)?);
1977 (record.payload.get(at..at + CMB_BRANCH_SUFFIX.len()) == Some(&CMB_BRANCH_SUFFIX))
1978 .then_some(())?;
1979 at += CMB_BRANCH_SUFFIX.len();
1980 }
1981 (record.payload.get(at..at + CMB_TAIL_PREFIX.len()) == Some(&CMB_TAIL_PREFIX))
1982 .then_some(())?;
1983 at += CMB_TAIL_PREFIX.len();
1984 references.push(decode_reference(&mut at)?);
1985 references.push(decode_reference(&mut at)?);
1986 (record.payload.get(at..at + CMB_TAIL_SUFFIX.len()) == Some(&CMB_TAIL_SUFFIX))
1987 .then_some(())?;
1988 Some(ProjectedCurvePayloadReferenceField { references })
1989 }
1990 _ => None,
1991 };
1992 let marker = match record.label.value {
1993 "CPROJ" => &[0x01, 0x02][..],
1994 "CPROJ_CMB" => &CMB_PREFIX[..],
1995 _ => return None,
1996 };
1997 let mut matches = Vec::new();
1998 for start in 0..=record.payload.len().saturating_sub(marker.len()) {
1999 if record.payload.get(start..start + marker.len()) != Some(marker) {
2000 continue;
2001 }
2002 if let Some(field) = decode_field(start) {
2003 matches.push(field);
2004 }
2005 }
2006 let [field] = matches.as_slice() else {
2007 return None;
2008 };
2009 Some(field.clone())
2010}
2011
2012pub fn pattern_payload_references(
2015 record: OperationRecord<'_>,
2016) -> Option<PatternPayloadReferenceField> {
2017 const GRAPH_SEPARATOR: [u8; 4] = [0xff, 0x00, 0xff, 0x01];
2018 const GRAPH_TAIL_PREFIX: [u8; 4] = [0xff, 0x00, 0x00, 0x01];
2019 const GRAPH_SUFFIX: [u8; 3] = [0xff, 0xff, 0x01];
2020 const INSTANCE_PREFIX: [u8; 3] = [0x00, 0xff, 0xff];
2021 const INSTANCE_SUFFIX: [u8; 17] = [
2022 0x01, 0x02, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
2023 0x01, 0x02,
2024 ];
2025 let decode_reference = |at: &mut usize| {
2026 let offset = *at;
2027 let (object_index, width) = payload_object_index(record.payload.get(offset..)?)?;
2028 *at += width;
2029 Some(PayloadObjectReference {
2030 offset: record.payload_offset + offset,
2031 object_index,
2032 raw_object_index: record.payload[offset..offset + width].to_vec(),
2033 })
2034 };
2035 let decode_graph = |start: usize| {
2036 let mut at = start + 1;
2037 let mut references = Vec::with_capacity(10);
2038 references.push(decode_reference(&mut at)?);
2039 (record.payload.get(at..at + GRAPH_SEPARATOR.len()) == Some(&GRAPH_SEPARATOR))
2040 .then_some(())?;
2041 at += GRAPH_SEPARATOR.len();
2042 references.push(decode_reference(&mut at)?);
2043 references.push(decode_reference(&mut at)?);
2044 (record.payload.get(at) == Some(&0x61)).then_some(())?;
2045 at += 1;
2046 references.push(decode_reference(&mut at)?);
2047 (record.payload.get(at..at + GRAPH_SEPARATOR.len()) == Some(&GRAPH_SEPARATOR))
2048 .then_some(())?;
2049 at += GRAPH_SEPARATOR.len();
2050 references.push(decode_reference(&mut at)?);
2051 references.push(decode_reference(&mut at)?);
2052 (record.payload.get(at..at + 2) == Some(&[0xff, 0x62])).then_some(())?;
2053 at += 2;
2054 references.push(decode_reference(&mut at)?);
2055 references.push(decode_reference(&mut at)?);
2056 (record.payload.get(at..at + GRAPH_TAIL_PREFIX.len()) == Some(&GRAPH_TAIL_PREFIX))
2057 .then_some(())?;
2058 at += GRAPH_TAIL_PREFIX.len();
2059 references.push(decode_reference(&mut at)?);
2060 if record.payload.get(at) == Some(&0xff) {
2061 at += 1;
2062 } else {
2063 references.push(decode_reference(&mut at)?);
2064 }
2065 (record.payload.get(at..at + GRAPH_SUFFIX.len()) == Some(&GRAPH_SUFFIX)).then_some(())?;
2066 Some(PatternPayloadReferenceField { references })
2067 };
2068 let decode_instance = |start: usize| {
2069 let mut at = start + INSTANCE_PREFIX.len();
2070 let reference = decode_reference(&mut at)?;
2071 (record.payload.get(at..at + INSTANCE_SUFFIX.len()) == Some(&INSTANCE_SUFFIX))
2072 .then_some(())?;
2073 Some(PatternPayloadReferenceField {
2074 references: vec![reference],
2075 })
2076 };
2077 let marker = match record.label.value {
2078 "Pattern Feature" | "Pattern Geometry" => &[0x61][..],
2079 "Geometry Instance" => &INSTANCE_PREFIX,
2080 _ => return None,
2081 };
2082 let matches = (0..=record.payload.len().saturating_sub(marker.len()))
2083 .filter(|&start| record.payload.get(start..start + marker.len()) == Some(marker))
2084 .filter_map(|start| match record.label.value {
2085 "Pattern Feature" | "Pattern Geometry" => decode_graph(start),
2086 "Geometry Instance" => decode_instance(start),
2087 _ => None,
2088 })
2089 .collect::<Vec<_>>();
2090 let [field] = matches.as_slice() else {
2091 return None;
2092 };
2093 Some(field.clone())
2094}
2095
2096pub fn pattern_payload_transform_lane(
2098 record: OperationRecord<'_>,
2099) -> Option<PatternPayloadTransformLane> {
2100 const FEATURE_PREFIX: [u8; 4] = [0x60, 0x01, 0x00, 0x00];
2101 const FEATURE_SCALAR_SUFFIX: [u8; 14] = [
2102 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x03,
2103 ];
2104 const GEOMETRY_PREFIX: [u8; 8] = [0x60, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00];
2105 const GEOMETRY_SCALAR_SUFFIX: [u8; 10] =
2106 [0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x03];
2107 const ROW_TAIL: [u8; 5] = [0x00, 0x00, 0xff, 0x00, 0x00];
2108 const TERMINATOR: [u8; 4] = [0x5f, 0x00, 0x00, 0x01];
2109
2110 let (prefix, scalar_suffix, encoding, scalar_width) = match record.label.value {
2111 "Pattern Feature" => (
2112 FEATURE_PREFIX.as_slice(),
2113 FEATURE_SCALAR_SUFFIX.as_slice(),
2114 PatternTransformEncoding::Binary32,
2115 4usize,
2116 ),
2117 "Pattern Geometry" => (
2118 GEOMETRY_PREFIX.as_slice(),
2119 GEOMETRY_SCALAR_SUFFIX.as_slice(),
2120 PatternTransformEncoding::Binary64,
2121 8usize,
2122 ),
2123 _ => return None,
2124 };
2125 let decode = |start: usize| {
2126 (record.payload.get(start) == Some(&0x01)).then_some(())?;
2127 let declared_count = *record.payload.get(start + 1)?;
2128 (declared_count >= 2).then_some(())?;
2129 let row_count = usize::from(declared_count - 1);
2130 let mut at = start + 2;
2131 let mut values = Vec::with_capacity(row_count);
2132 let mut value_offsets = Vec::with_capacity(row_count);
2133 let mut raw_values = Vec::with_capacity(row_count);
2134 let mut selectors = Vec::with_capacity(row_count);
2135 let mut raw_selectors = Vec::with_capacity(row_count);
2136 let mut selector_offsets = Vec::with_capacity(row_count);
2137 for ordinal in 1..declared_count {
2138 (record.payload.get(at..at + prefix.len()) == Some(prefix)).then_some(())?;
2139 at += prefix.len();
2140 let raw = record.payload.get(at..at + scalar_width)?;
2141 let (value, actual_encoding, width) = payload_scalar(raw)?;
2142 (actual_encoding
2143 == match encoding {
2144 PatternTransformEncoding::Binary32 => PayloadScalarEncoding::Binary32,
2145 PatternTransformEncoding::Binary64 => PayloadScalarEncoding::Binary64,
2146 }
2147 && width == scalar_width)
2148 .then_some(())?;
2149 values.push(value);
2150 value_offsets.push(record.payload_offset + at);
2151 raw_values.push(raw.to_vec());
2152 at += scalar_width;
2153 (record.payload.get(at..at + scalar_suffix.len()) == Some(scalar_suffix))
2154 .then_some(())?;
2155 at += scalar_suffix.len();
2156 let selector_offset = at;
2157 let (selector, width) = compact_index(record.payload.get(at..)?)?;
2158 let CompactIndex::Value(selector) = selector else {
2159 return None;
2160 };
2161 selectors.push(selector);
2162 raw_selectors.push(record.payload[at..at + width].to_vec());
2163 selector_offsets.push(record.payload_offset + selector_offset);
2164 at += width;
2165 (record.payload.get(at) == Some(&0x01)).then_some(())?;
2166 (record.payload.get(at + 1) == Some(&ordinal)).then_some(())?;
2167 (record.payload.get(at + 2..at + 2 + ROW_TAIL.len()) == Some(&ROW_TAIL))
2168 .then_some(())?;
2169 at += 2 + ROW_TAIL.len();
2170 }
2171 (record.payload.get(at..at + TERMINATOR.len()) == Some(&TERMINATOR)).then_some(())?;
2172 Some(PatternPayloadTransformLane {
2173 offset: record.payload_offset + start,
2174 declared_count,
2175 encoding,
2176 values,
2177 value_offsets,
2178 raw_values,
2179 selectors,
2180 raw_selectors,
2181 selector_offsets,
2182 })
2183 };
2184 let matches = (0..record.payload.len().saturating_sub(1))
2185 .filter_map(decode)
2186 .collect::<Vec<_>>();
2187 let [lane] = matches.as_slice() else {
2188 return None;
2189 };
2190 Some(lane.clone())
2191}
2192
2193pub fn point_feature_payload_header(
2195 record: OperationRecord<'_>,
2196) -> Option<PointFeaturePayloadHeader> {
2197 const PREFIX: [u8; 7] = [0x72, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00];
2198 const REFERENCE_SUFFIX: [u8; 42] = [
2199 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
2200 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x01, 0x02, 0x01, 0x00, 0x00, 0x00, 0x89,
2201 0x02, 0x01, 0x01, 0x01, 0x00, 0xa5, 0x57, 0x95, 0x01, 0x00, 0x00, 0xff,
2202 ];
2203 const MODE_SUFFIX: [u8; 20] = [
2204 0xc0, 0x1f, 0xff, 0xfd, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x03, 0x02, 0x01, 0x01, 0x01,
2205 0x00, 0x00, 0x00, 0x00, 0x00,
2206 ];
2207 if record.label.value != "POINT" || record.payload.get(..PREFIX.len()) != Some(&PREFIX) {
2208 return None;
2209 }
2210 let mut at = PREFIX.len();
2211 let reference_offset = at;
2212 let (object_index, width) = payload_object_index(record.payload.get(at..)?)?;
2213 at += width;
2214 (record.payload.get(at..at + REFERENCE_SUFFIX.len()) == Some(&REFERENCE_SUFFIX))
2215 .then_some(())?;
2216 at += REFERENCE_SUFFIX.len();
2217 let mode = *record.payload.get(at)?;
2218 matches!(mode, 0x02 | 0x03).then_some(())?;
2219 at += 1;
2220 (record.payload.get(at..at + MODE_SUFFIX.len()) == Some(&MODE_SUFFIX)).then_some(())?;
2221 Some(PointFeaturePayloadHeader {
2222 reference: PayloadObjectReference {
2223 offset: record.payload_offset + reference_offset,
2224 object_index,
2225 raw_object_index: record.payload[reference_offset..reference_offset + width].to_vec(),
2226 },
2227 mode,
2228 })
2229}
2230
2231pub fn point_feature_scalar_lane(
2233 preceding_block: &[u8],
2234 target_block: &[u8],
2235) -> Option<PointFeatureScalarLane> {
2236 const SUFFIX: [u8; 19] = [
2237 0x00, 0x25, 0x25, 0x41, 0x00, 0x04, 0x01, 0x07, 0x01, 0xc0, 0x45, 0x10, 0x00, 0x80, 0x86,
2238 0x02, 0x00, 0x01, 0x00,
2239 ];
2240 let preceding_start = preceding_block.len().checked_sub(3)?;
2241 (target_block.get(45..64) == Some(&SUFFIX)).then_some(())?;
2242 let mut lane = Vec::with_capacity(48);
2243 lane.extend_from_slice(&preceding_block[preceding_start..]);
2244 lane.extend_from_slice(target_block.get(..45)?);
2245 let raw_values: [[u8; 8]; 6] = lane
2246 .chunks_exact(8)
2247 .map(|bytes| bytes.try_into().expect("eight-byte chunk"))
2248 .collect::<Vec<_>>()
2249 .try_into()
2250 .ok()?;
2251 let values = raw_values
2252 .iter()
2253 .map(|bytes| shifted_ieee_f64(bytes))
2254 .collect::<Option<Vec<_>>>()?
2255 .try_into()
2256 .ok()?;
2257 Some(PointFeatureScalarLane {
2258 values,
2259 raw_values,
2260 value_offsets: [
2261 preceding_start,
2262 preceding_block.len() + 5,
2263 preceding_block.len() + 13,
2264 preceding_block.len() + 21,
2265 preceding_block.len() + 29,
2266 preceding_block.len() + 37,
2267 ],
2268 })
2269}
2270
2271pub fn draft_feature_payload_references(
2273 record: OperationRecord<'_>,
2274) -> Option<DraftFeaturePayloadReferenceField> {
2275 const PAYLOAD_PREFIX: [u8; 14] = [
2276 0x67, 0x00, 0x00, 0x01, 0x00, 0x2f, 0xa4, 0x7a, 0xe1, 0x47, 0xae, 0x14, 0x7b, 0x03,
2277 ];
2278 const GRAPH_PREFIX: [u8; 2] = [0x01, 0x02];
2279 const MIDDLE: [u8; 35] = [
2280 0x68, 0x2f, 0x70, 0x62, 0x4d, 0xd2, 0xf1, 0xa9, 0xfc, 0x03, 0x50, 0x44, 0x00, 0x00, 0x01,
2281 0x46, 0x8a, 0x2a, 0x01, 0xa3, 0x60, 0x10, 0x01, 0x01, 0x01, 0x04, 0x02, 0x01, 0x02, 0x01,
2282 0x00, 0x00, 0x00, 0x00, 0x01,
2283 ];
2284 if record.label.value != "DRAFT"
2285 || record.payload.get(..PAYLOAD_PREFIX.len()) != Some(&PAYLOAD_PREFIX)
2286 {
2287 return None;
2288 }
2289 let decode = |start: usize| {
2290 let mut at = start + GRAPH_PREFIX.len();
2291 let decode_reference = |at: &mut usize| {
2292 let offset = *at;
2293 let (object_index, width) = payload_object_index(record.payload.get(offset..)?)?;
2294 *at += width;
2295 Some(PayloadObjectReference {
2296 offset: record.payload_offset + offset,
2297 object_index,
2298 raw_object_index: record.payload[offset..offset + width].to_vec(),
2299 })
2300 };
2301 let first = decode_reference(&mut at)?;
2302 (record.payload.get(at..at + GRAPH_PREFIX.len()) == Some(&GRAPH_PREFIX)).then_some(())?;
2303 at += GRAPH_PREFIX.len();
2304 let second = decode_reference(&mut at)?;
2305 (record.payload.get(at..at + MIDDLE.len()) == Some(&MIDDLE)).then_some(())?;
2306 at += MIDDLE.len();
2307 let third = decode_reference(&mut at)?;
2308 (record.payload.get(at..at + 4) == Some(&[0xff, 0x00, 0x00, 0x00])).then_some(())?;
2309 at += 4;
2310 let fourth = decode_reference(&mut at)?;
2311 (record.payload.get(at) == Some(&0xff)).then_some(())?;
2312 Some(DraftFeaturePayloadReferenceField {
2313 references: [first, second, third, fourth],
2314 })
2315 };
2316 let matches = (PAYLOAD_PREFIX.len()..=record.payload.len().saturating_sub(GRAPH_PREFIX.len()))
2317 .filter(|&start| {
2318 record.payload.get(start..start + GRAPH_PREFIX.len()) == Some(&GRAPH_PREFIX)
2319 })
2320 .filter_map(decode)
2321 .collect::<Vec<_>>();
2322 let [field] = matches.as_slice() else {
2323 return None;
2324 };
2325 Some(field.clone())
2326}
2327
2328pub fn draft_feature_leading_index_lane(
2330 record: OperationRecord<'_>,
2331) -> Option<DraftFeatureLeadingIndexLane> {
2332 const PREFIX: [u8; 22] = [
2333 0x67, 0x00, 0x00, 0x01, 0x00, 0x2f, 0xa4, 0x7a, 0xe1, 0x47, 0xae, 0x14, 0x7b, 0x03, 0xff,
2334 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2335 ];
2336 if record.label.value != "DRAFT" || record.payload.get(..PREFIX.len()) != Some(&PREFIX) {
2337 return None;
2338 }
2339 let mut at = PREFIX.len();
2340 (record.payload.get(at) == Some(&0x01)).then_some(())?;
2341 let declared_count = *record.payload.get(at + 1)?;
2342 (declared_count >= 2).then_some(())?;
2343 at += 2;
2344 let mut indices = Vec::with_capacity(usize::from(declared_count - 1));
2345 let mut raw_indices = Vec::with_capacity(usize::from(declared_count - 1));
2346 for _ in 1..declared_count {
2347 let offset = at;
2348 let (CompactIndex::Value(value), width) = compact_index(record.payload.get(at..)?)? else {
2349 return None;
2350 };
2351 at += width;
2352 indices.push((value, record.payload_offset + offset));
2353 raw_indices.push(record.payload[offset..offset + width].to_vec());
2354 }
2355 (record.payload.get(at..at + 2) == Some(&[0x01, 0x02])).then_some(())?;
2356 Some(DraftFeatureLeadingIndexLane {
2357 declared_count,
2358 indices,
2359 raw_indices,
2360 })
2361}
2362
2363pub fn draft_feature_terminal_lane(
2365 record: OperationRecord<'_>,
2366) -> Option<DraftFeatureTerminalLane> {
2367 const FIXED: [u8; 11] = [
2368 0x01, 0x03, 0x02, 0x01, 0x02, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00,
2369 ];
2370 if record.label.value != "DRAFT" {
2371 return None;
2372 }
2373 let mut matches = Vec::new();
2374 for start in 0..record.payload.len() {
2375 let mut at = start;
2376 let first_offset = at;
2377 if !record
2378 .payload
2379 .get(at)
2380 .is_some_and(|marker| (0x80..=0xfe).contains(marker))
2381 {
2382 continue;
2383 }
2384 let Some((CompactIndex::Value(first), first_width)) =
2385 record.payload.get(at..).and_then(compact_index)
2386 else {
2387 continue;
2388 };
2389 at += first_width;
2390 let second_offset = at;
2391 if !record
2392 .payload
2393 .get(at)
2394 .is_some_and(|marker| (0x80..=0xfe).contains(marker))
2395 {
2396 continue;
2397 }
2398 let Some((CompactIndex::Value(second), second_width)) =
2399 record.payload.get(at..).and_then(compact_index)
2400 else {
2401 continue;
2402 };
2403 at += second_width;
2404 if record.payload.get(at..at + FIXED.len()) != Some(&FIXED) {
2405 continue;
2406 }
2407 at += FIXED.len();
2408 let Some(tail) = record
2409 .payload
2410 .get(at..at + 3)
2411 .and_then(|bytes| bytes.try_into().ok())
2412 else {
2413 continue;
2414 };
2415 at += 3;
2416 if at + 1 != record.payload.len() || record.payload.get(at) != Some(&0x00) {
2417 continue;
2418 }
2419 matches.push(DraftFeatureTerminalLane {
2420 indices: [first, second],
2421 raw_indices: [
2422 record.payload[first_offset..first_offset + first_width]
2423 .try_into()
2424 .ok()?,
2425 record.payload[second_offset..second_offset + second_width]
2426 .try_into()
2427 .ok()?,
2428 ],
2429 index_offsets: [
2430 record.payload_offset + first_offset,
2431 record.payload_offset + second_offset,
2432 ],
2433 tail,
2434 offset: record.payload_offset + start,
2435 });
2436 }
2437 let [lane] = matches.as_slice() else {
2438 return None;
2439 };
2440 Some(lane.clone())
2441}
2442
2443pub fn surface_feature_payload_references(
2446 record: OperationRecord<'_>,
2447) -> Option<SurfaceFeaturePayloadReferenceField> {
2448 const HEADER_PREFIX: [u8; 4] = [0x00, 0x00, 0x01, 0x00];
2449 const TRAILING_PREFIX: [u8; 10] = [0x03, 0x03, 0x2f, 0xa4, 0x7a, 0xe1, 0x47, 0xae, 0x14, 0x7b];
2450 const TRAILING_SUFFIX: [u8; 17] = [
2451 0x01, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
2452 0x01, 0x02,
2453 ];
2454 let discriminator = *record.payload.first()?;
2455 match record.label.value {
2456 "SKIN" if matches!(discriminator, 0x3e | 0x3f) => {}
2457 "Studio Surface" if discriminator == 0x14 => {}
2458 _ => return None,
2459 }
2460 (record.payload.get(1..5) == Some(&HEADER_PREFIX)).then_some(())?;
2461 let decode_reference = |at: &mut usize| {
2462 let offset = *at;
2463 let (object_index, width) = payload_object_index(record.payload.get(offset..)?)?;
2464 *at += width;
2465 Some(PayloadObjectReference {
2466 offset: record.payload_offset + offset,
2467 object_index,
2468 raw_object_index: record.payload[offset..offset + width].to_vec(),
2469 })
2470 };
2471 let mut at = 5;
2472 let mut references = Vec::with_capacity(14);
2473 for _ in 0..3 {
2474 references.push(decode_reference(&mut at)?);
2475 }
2476 (record.payload.get(at..at + 2) == Some(&[0x01, 0x09])).then_some(())?;
2477 at += 2;
2478 record.payload.get(at..at + 8)?;
2479 at += 8;
2480 (record.payload.get(at..at + 2) == Some(&[0x01, 0x09])).then_some(())?;
2481 at += 2;
2482 for _ in 0..8 {
2483 references.push(decode_reference(&mut at)?);
2484 }
2485
2486 let trailing_starts = record
2487 .payload
2488 .windows(TRAILING_PREFIX.len())
2489 .enumerate()
2490 .filter_map(|(start, bytes)| (bytes == TRAILING_PREFIX).then_some(start))
2491 .collect::<Vec<_>>();
2492 let [trailing_start] = trailing_starts.as_slice() else {
2493 return None;
2494 };
2495 at = trailing_start + TRAILING_PREFIX.len();
2496 for _ in 0..3 {
2497 references.push(decode_reference(&mut at)?);
2498 }
2499 (record.payload.get(at..at + TRAILING_SUFFIX.len()) == Some(&TRAILING_SUFFIX)).then_some(())?;
2500 Some(SurfaceFeaturePayloadReferenceField {
2501 references: references.try_into().ok()?,
2502 })
2503}
2504
2505fn surface_feature_branch_paths(
2506 payload: &[u8],
2507 payload_offset: usize,
2508 at: usize,
2509 remaining: u8,
2510 terminator: &[u8],
2511) -> Vec<Vec<SurfaceFeaturePayloadBranch>> {
2512 if remaining == 0 || !matches!(payload.get(at), Some(0x16 | 0x40)) {
2513 return Vec::new();
2514 }
2515 let mode = payload[at];
2516 if payload.get(at + 1) != Some(&0x01) {
2517 return Vec::new();
2518 }
2519 let Some(declared_count @ 2..) = payload.get(at + 2).copied() else {
2520 return Vec::new();
2521 };
2522 let mut cursor = at + 3;
2523 let mut members = Vec::with_capacity(usize::from(declared_count) - 1);
2524 for _ in 1..declared_count {
2525 let Some((object_index, width)) = payload.get(cursor..).and_then(payload_object_index)
2526 else {
2527 return Vec::new();
2528 };
2529 members.push(PayloadObjectReference {
2530 offset: payload_offset + cursor,
2531 object_index,
2532 raw_object_index: payload[cursor..cursor + width].to_vec(),
2533 });
2534 cursor += width;
2535 }
2536 let witnessed = payload.get(cursor..cursor + 2) == Some(&[0x01, declared_count]);
2537 if witnessed {
2538 cursor += 2;
2539 }
2540 let zero_count = if witnessed {
2541 usize::from(declared_count) + 3
2542 } else {
2543 5
2544 };
2545 let Some(zero_lane) = payload.get(cursor..cursor + zero_count) else {
2546 return Vec::new();
2547 };
2548 if !zero_lane.iter().all(|&byte| byte == 0) {
2549 return Vec::new();
2550 }
2551 cursor += zero_count;
2552 if payload.get(cursor..cursor + 3) != Some(&[0xff, 0x01, 0x02]) {
2553 return Vec::new();
2554 }
2555 cursor += 3;
2556 let Some((object_index, width)) = payload.get(cursor..).and_then(payload_object_index) else {
2557 return Vec::new();
2558 };
2559 let terminal = PayloadObjectReference {
2560 offset: payload_offset + cursor,
2561 object_index,
2562 raw_object_index: payload[cursor..cursor + width].to_vec(),
2563 };
2564 cursor += width;
2565 if payload.get(cursor) != Some(&0x00) {
2566 return Vec::new();
2567 }
2568 cursor += 1;
2569
2570 let mut paths = Vec::new();
2571 for suffix_len in 1..=5 {
2572 let Some(suffix) = payload.get(cursor..cursor + suffix_len) else {
2573 continue;
2574 };
2575 let next = cursor + suffix_len;
2576 let continuations = if remaining == 1 {
2577 (payload.get(next..next + terminator.len()) == Some(terminator))
2578 .then_some(Vec::new())
2579 .into_iter()
2580 .collect::<Vec<_>>()
2581 } else {
2582 surface_feature_branch_paths(payload, payload_offset, next, remaining - 1, terminator)
2583 };
2584 for mut continuation in continuations {
2585 let branch = SurfaceFeaturePayloadBranch {
2586 offset: payload_offset + at,
2587 mode,
2588 declared_count,
2589 witnessed,
2590 members: members.clone(),
2591 terminal: terminal.clone(),
2592 suffix: suffix.to_vec(),
2593 };
2594 continuation.insert(0, branch);
2595 paths.push(continuation);
2596 if paths.len() == 2 {
2597 return paths;
2598 }
2599 }
2600 }
2601 paths
2602}
2603
2604pub fn surface_feature_payload_branches(
2607 record: OperationRecord<'_>,
2608) -> Option<SurfaceFeaturePayloadBranches> {
2609 const SKIN_TERMINATOR: [u8; 11] = [
2610 0x00, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x00, 0xff, 0xff, 0x01,
2611 ];
2612 const STUDIO_TERMINATOR: [u8; 8] = [0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x01];
2613 let terminator = match record.label.value {
2614 "SKIN" => &SKIN_TERMINATOR[..],
2615 "Studio Surface" => &STUDIO_TERMINATOR[..],
2616 _ => return None,
2617 };
2618 let mut matches = Vec::new();
2619 for start in 0..record.payload.len().saturating_sub(6) {
2620 if record.payload.get(start..start + 2) != Some(&[0xa0, 0x5a]) {
2621 continue;
2622 }
2623 let Some(family @ (0x14 | 0x50)) = record.payload.get(start + 2).copied() else {
2624 continue;
2625 };
2626 let Some(header_code) = record.payload.get(start + 3).copied() else {
2627 continue;
2628 };
2629 if record.payload.get(start + 4) != Some(&0x01) {
2630 continue;
2631 }
2632 let Some(declared_group_count @ 1..) = record.payload.get(start + 5).copied() else {
2633 continue;
2634 };
2635 let paths = surface_feature_branch_paths(
2636 record.payload,
2637 record.payload_offset,
2638 start + 6,
2639 declared_group_count,
2640 terminator,
2641 );
2642 let [branches] = paths.as_slice() else {
2643 continue;
2644 };
2645 matches.push(SurfaceFeaturePayloadBranches {
2646 family,
2647 header_code,
2648 branches: branches.clone(),
2649 });
2650 }
2651 let [group] = matches.as_slice() else {
2652 return None;
2653 };
2654 Some(group.clone())
2655}
2656
2657pub fn extrude_profile_references(
2659 record: OperationRecord<'_>,
2660) -> Option<ExtrudeProfileReferenceField> {
2661 if record.label.value != "EXTRUDE" {
2662 return None;
2663 }
2664 let mut matches = Vec::new();
2665 for start in 0..record.payload.len().saturating_sub(6) {
2666 if record.payload.get(start..start + 4) != Some(&[0x01, 0x02, 0x16, 0x01]) {
2667 continue;
2668 }
2669 let Some(references) = extrude_profile_reference_field(record, start) else {
2670 continue;
2671 };
2672 matches.push(references);
2673 }
2674 let [references] = matches.as_slice() else {
2675 return None;
2676 };
2677 Some(references.clone())
2678}
2679
2680pub fn extrude_payload_header(record: OperationRecord<'_>) -> Option<ExtrudePayloadHeader> {
2682 if record.label.value != "EXTRUDE"
2683 || record.payload.get(..5) != Some(&[0x0f, 0x00, 0x00, 0x01, 0x00])
2684 {
2685 return None;
2686 }
2687 let raw_scalars = [
2688 <[u8; 8]>::try_from(record.payload.get(5..13)?).ok()?,
2689 <[u8; 8]>::try_from(record.payload.get(13..21)?).ok()?,
2690 ];
2691 Some(ExtrudePayloadHeader {
2692 offset: record.payload_offset + 5,
2693 scalars: [
2694 shifted_ieee_f64(&raw_scalars[0])?,
2695 shifted_ieee_f64(&raw_scalars[1])?,
2696 ],
2697 raw_scalars,
2698 })
2699}
2700
2701pub fn extrude_payload_footer(record: OperationRecord<'_>) -> Option<ExtrudePayloadFooter> {
2703 if record.label.value != "EXTRUDE" || record.payload.last() != Some(&0) {
2704 return None;
2705 }
2706 let mut matches = Vec::new();
2707 for start in 0..record.payload.len().saturating_sub(18) {
2708 if record.payload.get(start..start + 3) != Some(&[0x01, 0x01, 0x02]) {
2709 continue;
2710 }
2711 let mut at = start + 3;
2712 let mut type_indices = [0; 2];
2713 let mut raw_type_indices = Vec::with_capacity(2);
2714 let mut type_index_offsets = Vec::with_capacity(2);
2715 let mut valid = true;
2716 for value in &mut type_indices {
2717 let Some((CompactIndex::Value(index), width)) =
2718 record.payload.get(at..).and_then(compact_index)
2719 else {
2720 valid = false;
2721 break;
2722 };
2723 *value = index;
2724 raw_type_indices.push(record.payload[at..at + width].to_vec());
2725 type_index_offsets.push(record.payload_offset + at);
2726 at += width;
2727 }
2728 let Ok(raw_type_indices) = raw_type_indices.try_into() else {
2729 continue;
2730 };
2731 let Ok(type_index_offsets) = type_index_offsets.try_into() else {
2732 continue;
2733 };
2734 if !valid || record.payload.get(at..at + 4) != Some(&[0x01, 0x03, 0x02, 0x01]) {
2735 continue;
2736 }
2737 at += 4;
2738 let Some(flags) = record
2739 .payload
2740 .get(at..at + 4)
2741 .and_then(|bytes| bytes.try_into().ok())
2742 else {
2743 continue;
2744 };
2745 at += 4;
2746 if record.payload.get(at..at + 5) != Some(&[0x00, 0x00, 0x00, 0x29, 0x29]) {
2747 continue;
2748 }
2749 at += 5;
2750 let trailing_end = record.payload.len() - 1;
2751 let mut trailing_indices = Vec::new();
2752 let mut raw_trailing_indices = Vec::new();
2753 let mut trailing_index_offsets = Vec::new();
2754 while at < trailing_end {
2755 let Some((CompactIndex::Value(value), width)) =
2756 record.payload.get(at..trailing_end).and_then(compact_index)
2757 else {
2758 valid = false;
2759 break;
2760 };
2761 trailing_indices.push(value);
2762 raw_trailing_indices.push(record.payload[at..at + width].to_vec());
2763 trailing_index_offsets.push(record.payload_offset + at);
2764 at += width;
2765 }
2766 if !valid || at != trailing_end {
2767 continue;
2768 }
2769 matches.push(ExtrudePayloadFooter {
2770 offset: record.payload_offset + start,
2771 type_indices,
2772 raw_type_indices,
2773 type_index_offsets,
2774 mode_indices: [2, 1],
2775 flags,
2776 trailing_indices,
2777 raw_trailing_indices,
2778 trailing_index_offsets,
2779 });
2780 }
2781 let [footer] = matches.as_slice() else {
2782 return None;
2783 };
2784 Some(footer.clone())
2785}
2786
2787fn shifted_ieee_f64(bytes: &[u8]) -> Option<f64> {
2788 let encoded: [u8; 8] = bytes.try_into().ok()?;
2789 let mut raw = encoded;
2790 raw[0] = raw[0].checked_add(0x10)?;
2791 let value = f64::from_be_bytes(raw);
2792 value.is_finite().then_some(value)
2793}
2794
2795pub fn operation_body_scalar_triples(
2797 record: OperationRecord<'_>,
2798) -> Vec<OperationBodyScalarTriple> {
2799 operation_body_references(record)
2800 .into_iter()
2801 .enumerate()
2802 .filter_map(|(ordinal, reference)| {
2803 let token = reference.offset.checked_sub(record.offset)?;
2804 let (_, end) = feature_object_index(record.bytes, token)?;
2805 if record.bytes.get(end) != Some(&0xff) {
2806 return None;
2807 }
2808 let branch = *record.bytes.get(end + 1)?;
2809 let mut at = end + 2;
2810 let mut scalars = Vec::with_capacity(3);
2811 for _ in 0..3 {
2812 let (value, encoding, width) = payload_scalar(record.bytes.get(at..)?)?;
2813 scalars.push(PayloadScalar {
2814 offset: record.offset + at,
2815 value,
2816 encoding,
2817 raw_value: record.bytes.get(at..at + width)?.to_vec(),
2818 });
2819 at += width;
2820 }
2821 Some(OperationBodyScalarTriple {
2822 body_reference_ordinal: ordinal as u32,
2823 body_object_index: reference.object_index,
2824 branch,
2825 scalars: scalars.try_into().ok()?,
2826 })
2827 })
2828 .collect()
2829}
2830
2831pub fn operation_body_members(record: OperationRecord<'_>) -> Vec<OperationBodyMember> {
2833 operation_body_references(record)
2834 .into_iter()
2835 .enumerate()
2836 .flat_map(|(body_ordinal, reference)| {
2837 let Some(token) = reference.offset.checked_sub(record.offset) else {
2838 return Vec::new();
2839 };
2840 let Some((_, end)) = feature_object_index(record.bytes, token) else {
2841 return Vec::new();
2842 };
2843 if record.bytes.get(end..end + 2) != Some(&[0xff, 0x11]) {
2844 return Vec::new();
2845 }
2846 let mut at = end + 2;
2847 for _ in 0..3 {
2848 let Some((_, _, width)) = record.bytes.get(at..).and_then(payload_scalar) else {
2849 return Vec::new();
2850 };
2851 at += width;
2852 }
2853 if record.bytes.get(at) != Some(&0x01) {
2854 return Vec::new();
2855 }
2856 let Some(count) = record.bytes.get(at + 1).copied().map(usize::from) else {
2857 return Vec::new();
2858 };
2859 if count < 2 {
2860 return Vec::new();
2861 }
2862 at += 2;
2863 let mut members = Vec::with_capacity(count - 1);
2864 for ordinal in 0..count - 1 {
2865 if record.bytes.get(at) != Some(&0x2e) {
2866 return Vec::new();
2867 }
2868 at += 1;
2869 let member_at = at;
2870 let Some((CompactIndex::Value(member_index), width)) =
2871 record.bytes.get(at..).and_then(compact_index)
2872 else {
2873 return Vec::new();
2874 };
2875 at += width;
2876 if record.bytes.get(at) != Some(&0x00) {
2877 return Vec::new();
2878 }
2879 at += 1;
2880 members.push(OperationBodyMember {
2881 body_reference_ordinal: body_ordinal as u32,
2882 body_object_index: reference.object_index,
2883 ordinal: ordinal as u32,
2884 member_index,
2885 raw_member_index: record.bytes[member_at..member_at + width].to_vec(),
2886 offset: record.offset + member_at,
2887 });
2888 }
2889 members
2890 })
2891 .collect()
2892}
2893
2894pub fn operation_body_11_continuations(
2896 record: OperationRecord<'_>,
2897) -> Vec<OperationBody11Continuation> {
2898 if record.label.value != "TRIM BODY" {
2899 return Vec::new();
2900 }
2901 operation_body_references(record)
2902 .into_iter()
2903 .enumerate()
2904 .filter_map(|(body_ordinal, reference)| {
2905 let token = reference.offset.checked_sub(record.offset)?;
2906 let (_, end) = feature_object_index(record.bytes, token)?;
2907 if record.bytes.get(end..end + 2) != Some(&[0xff, 0x11]) {
2908 return None;
2909 }
2910 let mut at = end + 2;
2911 for _ in 0..3 {
2912 let (_, _, width) = payload_scalar(record.bytes.get(at..)?)?;
2913 at += width;
2914 }
2915 if record.bytes.get(at) != Some(&0x01) {
2916 return None;
2917 }
2918 let member_count = usize::from(*record.bytes.get(at + 1)?);
2919 if member_count < 2 {
2920 return None;
2921 }
2922 at += 2;
2923 for _ in 0..member_count - 1 {
2924 if record.bytes.get(at) != Some(&0x2e) {
2925 return None;
2926 }
2927 at += 1;
2928 let (CompactIndex::Value(_), width) = compact_index(record.bytes.get(at..)?)?
2929 else {
2930 return None;
2931 };
2932 at += width;
2933 if record.bytes.get(at) != Some(&0x00) {
2934 return None;
2935 }
2936 at += 1;
2937 }
2938 if record.bytes.get(at..at + 2) != Some(&[0x01, 0x02]) {
2939 return None;
2940 }
2941 at += 2;
2942 let continuation_at = at;
2943 let (CompactIndex::Value(continuation_index), width) =
2944 compact_index(record.bytes.get(at..)?)?
2945 else {
2946 return None;
2947 };
2948 at += width;
2949 if record.bytes.get(at..at + 3) != Some(&[0x00, 0x00, 0x01]) {
2950 return None;
2951 }
2952 at += 3;
2953 let terminal_at = at;
2954 let (Some(terminal_object_index), next) = feature_object_index(record.bytes, at)?
2955 else {
2956 return None;
2957 };
2958 if record.bytes.get(next..next + 2) != Some(&[0x00, 0x00]) {
2959 return None;
2960 }
2961 Some(OperationBody11Continuation {
2962 body_reference_ordinal: body_ordinal as u32,
2963 body_object_index: reference.object_index,
2964 continuation_index,
2965 raw_continuation_index: record.bytes[continuation_at..continuation_at + width]
2966 .to_vec(),
2967 continuation_offset: record.offset + continuation_at,
2968 terminal_object_index,
2969 raw_terminal_object_index: record.bytes[terminal_at..next].to_vec(),
2970 terminal_offset: record.offset + terminal_at,
2971 })
2972 })
2973 .collect()
2974}
2975
2976pub fn operation_body_reference_lanes(
2978 record: OperationRecord<'_>,
2979) -> Vec<OperationBodyReferenceLane> {
2980 operation_body_references(record)
2981 .into_iter()
2982 .enumerate()
2983 .filter_map(|(body_ordinal, reference)| {
2984 let token = reference.offset.checked_sub(record.offset)?;
2985 let (_, end) = feature_object_index(record.bytes, token)?;
2986 if record.bytes.get(end) != Some(&0xff) {
2987 return None;
2988 }
2989 let branch = *record.bytes.get(end + 1)?;
2990 if !matches!(branch, 0x11 | 0x1c) {
2991 return None;
2992 }
2993 let mut at = end + 2;
2994 for _ in 0..3 {
2995 let (_, _, width) = payload_scalar(record.bytes.get(at..)?)?;
2996 at += width;
2997 }
2998 if record.bytes.get(at) != Some(&0x01) {
2999 return None;
3000 }
3001 let count = usize::from(*record.bytes.get(at + 1)?);
3002 if count < 2 {
3003 return None;
3004 }
3005 at += 2;
3006 let compact = operation_body_reference_lane_values(
3007 record,
3008 at,
3009 count - 1,
3010 OperationBodyReferenceLaneEncoding::CompactIndex,
3011 );
3012 let objects = operation_body_reference_lane_values(
3013 record,
3014 at,
3015 count - 1,
3016 OperationBodyReferenceLaneEncoding::PayloadObjectIndex,
3017 );
3018 let (encoding, values) = match (compact, objects) {
3019 (Some(values), None) => (OperationBodyReferenceLaneEncoding::CompactIndex, values),
3020 (None, Some(values)) => (
3021 OperationBodyReferenceLaneEncoding::PayloadObjectIndex,
3022 values,
3023 ),
3024 _ => return None,
3025 };
3026 Some(OperationBodyReferenceLane {
3027 body_reference_ordinal: body_ordinal as u32,
3028 body_object_index: reference.object_index,
3029 branch,
3030 encoding,
3031 values,
3032 })
3033 })
3034 .collect()
3035}
3036
3037fn operation_body_reference_lane_values(
3038 record: OperationRecord<'_>,
3039 mut at: usize,
3040 count: usize,
3041 encoding: OperationBodyReferenceLaneEncoding,
3042) -> Option<Vec<OperationBodyReferenceLaneValue>> {
3043 let mut values = Vec::with_capacity(count);
3044 for ordinal in 0..count {
3045 let value_at = at;
3046 let (object_index, width) = match encoding {
3047 OperationBodyReferenceLaneEncoding::CompactIndex => {
3048 let (CompactIndex::Value(value), width) = compact_index(record.bytes.get(at..)?)?
3049 else {
3050 return None;
3051 };
3052 (value, width)
3053 }
3054 OperationBodyReferenceLaneEncoding::PayloadObjectIndex => {
3055 payload_object_index(record.bytes.get(at..)?)?
3056 }
3057 };
3058 at += width;
3059 values.push(OperationBodyReferenceLaneValue {
3060 ordinal: ordinal as u32,
3061 object_index,
3062 raw_value: record.bytes[value_at..value_at + width].to_vec(),
3063 offset: record.offset + value_at,
3064 });
3065 }
3066 (record.bytes.get(at..at + 4) == Some(&[0x00, 0x00, 0x0b, 0x00])).then_some(values)
3067}
3068
3069pub fn extrude_payload_32_branch(record: OperationRecord<'_>) -> Option<ExtrudePayload32Branch> {
3071 if record.label.value != "EXTRUDE" {
3072 return None;
3073 }
3074 let reference = operation_body_reference(record)?;
3075 let token = reference.offset.checked_sub(record.offset)?;
3076 let (_, end) = feature_object_index(record.bytes, token)?;
3077 if record.bytes.get(end..end + 4) != Some(&[0xff, 0x32, 0x00, 0x00]) {
3078 return None;
3079 }
3080 let branch_at = end + 1;
3081 let raw_scalar = <[u8; 8]>::try_from(record.bytes.get(end + 4..end + 12)?).ok()?;
3082 let scalar = shifted_ieee_f64(&raw_scalar)?;
3083 let mut at = end + 12;
3084 let (atoms_be, atom_offsets) = counted_u32_atoms(record.bytes, &mut at)?;
3085 let atom_indices = atoms_be
3086 .iter()
3087 .map(|atom| {
3088 let bytes = atom.to_be_bytes();
3089 if bytes[0] != 0x3d || bytes[3] != 0x00 || !(0x80..=0xfe).contains(&bytes[1]) {
3090 return None;
3091 }
3092 Some(u32::from(bytes[1] - 0x80) * 256 + u32::from(bytes[2]))
3093 })
3094 .collect::<Option<Vec<_>>>()?;
3095 let first = counted_compact_values(record.bytes, &mut at)?;
3096 let second = counted_compact_values(record.bytes, &mut at)?;
3097 if record.bytes.get(at..at + 2) != Some(&[0x00, 0x01]) {
3098 return None;
3099 }
3100 let (terminal_object_index, next) = feature_object_index(record.bytes, at + 2)?;
3101 let terminal_object_index = terminal_object_index?;
3102 if terminal_object_index != reference.object_index
3103 || record.bytes.get(next..next + 2) != Some(&[0x00, 0x00])
3104 {
3105 return None;
3106 }
3107 Some(ExtrudePayload32Branch {
3108 offset: record.offset + branch_at,
3109 body_object_index: reference.object_index,
3110 scalar,
3111 raw_scalar,
3112 atoms_be,
3113 atom_offsets: atom_offsets
3114 .into_iter()
3115 .map(|offset| record.offset + offset)
3116 .collect(),
3117 atom_indices,
3118 first_indices: first.values,
3119 raw_first_indices: first.raw_values,
3120 first_index_offsets: first
3121 .offsets
3122 .into_iter()
3123 .map(|offset| record.offset + offset)
3124 .collect(),
3125 second_indices: second.values,
3126 raw_second_indices: second.raw_values,
3127 second_index_offsets: second
3128 .offsets
3129 .into_iter()
3130 .map(|offset| record.offset + offset)
3131 .collect(),
3132 terminal_object_index,
3133 raw_terminal_object_index: record.bytes[at + 2..next].to_vec(),
3134 terminal_offset: record.offset + at + 2,
3135 })
3136}
3137
3138pub fn block_construction_references(
3140 record: OperationRecord<'_>,
3141) -> Option<BlockConstructionReferenceField> {
3142 const TRAILER: [u8; 15] = [
3143 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
3144 ];
3145 if record.label.value != "BLOCK"
3146 || record.payload.get(1..6) != Some(&[0x00, 0x00, 0x01, 0x00, 0x00])
3147 {
3148 return None;
3149 }
3150 let mut at = 6usize;
3151 let mut references = Vec::with_capacity(19);
3152 for _ in 0..18 {
3153 let (object_index, width) = payload_object_index(record.payload.get(at..)?)?;
3154 references.push(PayloadObjectReference {
3155 offset: record.payload_offset + at,
3156 object_index,
3157 raw_object_index: record.payload[at..at + width].to_vec(),
3158 });
3159 at += width;
3160 }
3161 if record.payload.get(at) != Some(&0x01) {
3162 return None;
3163 }
3164 at += 1;
3165 let (object_index, width) = payload_object_index(record.payload.get(at..)?)?;
3166 references.push(PayloadObjectReference {
3167 offset: record.payload_offset + at,
3168 object_index,
3169 raw_object_index: record.payload[at..at + width].to_vec(),
3170 });
3171 at += width;
3172 if record.payload.get(at..at + TRAILER.len()) != Some(&TRAILER) {
3173 return None;
3174 }
3175 Some(BlockConstructionReferenceField {
3176 control: record.payload[0],
3177 references,
3178 })
3179}
3180
3181pub fn datum_csys_references(record: OperationRecord<'_>) -> Option<DatumCsysReferenceField> {
3184 const HEADER_SUFFIX: [u8; 13] = [
3185 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
3186 ];
3187 const TRAILER: [u8; 8] = [0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00];
3188 if record.label.value != "DATUM_CSYS"
3189 || record.payload.get(1..1 + HEADER_SUFFIX.len()) != Some(&HEADER_SUFFIX)
3190 {
3191 return None;
3192 }
3193 let mut at = 1 + HEADER_SUFFIX.len();
3194 let mut references = Vec::with_capacity(8);
3195 for _ in 0..8 {
3196 let (object_index, width) = payload_object_index(record.payload.get(at..)?)?;
3197 references.push(PayloadObjectReference {
3198 offset: record.payload_offset + at,
3199 object_index,
3200 raw_object_index: record.payload[at..at + width].to_vec(),
3201 });
3202 at += width;
3203 }
3204 (record.payload.get(at..at + TRAILER.len()) == Some(&TRAILER)).then_some(())?;
3205 Some(DatumCsysReferenceField {
3206 control: record.payload[0],
3207 references: references.try_into().ok()?,
3208 })
3209}
3210
3211pub fn datum_plane_payload_header(record: OperationRecord<'_>) -> Option<DatumPlanePayloadHeader> {
3213 const PREFIX: [u8; 5] = [0x00, 0x00, 0x01, 0x00, 0x01];
3214 if record.label.value != "DATUM_PLANE"
3215 || record.payload.get(1..6) != Some(&PREFIX)
3216 || record.payload.get(8..10) != Some(&[0x01, 0x02])
3217 {
3218 return None;
3219 }
3220 let declared_count = *record.payload.get(6)?;
3221 (declared_count >= 2).then_some(DatumPlanePayloadHeader {
3222 control: record.payload[0],
3223 declared_count,
3224 branch_tag: record.payload[7],
3225 })
3226}
3227
3228pub fn datum_plane_single_reference_branch(
3230 record: OperationRecord<'_>,
3231) -> Option<DatumPlaneSingleReferenceBranch> {
3232 const SUFFIX: [u8; 12] = [
3233 0x00, 0x14, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00,
3234 ];
3235 let header = datum_plane_payload_header(record)?;
3236 if header.declared_count != 2 || !matches!(header.branch_tag, 0x1b | 0x23) {
3237 return None;
3238 }
3239 let mut at = 10;
3240 let descriptor_offset = record.payload_offset + at;
3241 let (CompactIndex::Value(descriptor_index), width) = compact_index(record.payload.get(at..)?)?
3242 else {
3243 return None;
3244 };
3245 let raw_descriptor_index = record.payload[at..at + width].to_vec();
3246 at += width;
3247 (record.payload.get(at) == Some(&0x01)).then_some(())?;
3248 at += 1;
3249 let object_offset = record.payload_offset + at;
3250 let (object_index, width) = payload_object_index(record.payload.get(at..)?)?;
3251 let raw_object_index = record.payload[at..at + width].to_vec();
3252 at += width;
3253 (record.payload.get(at..at + SUFFIX.len()) == Some(&SUFFIX)).then_some(())?;
3254 Some(DatumPlaneSingleReferenceBranch {
3255 descriptor_index,
3256 raw_descriptor_index,
3257 descriptor_offset,
3258 object_index,
3259 raw_object_index,
3260 object_offset,
3261 })
3262}
3263
3264pub fn datum_plane_descriptor_reference_branch(
3266 record: OperationRecord<'_>,
3267) -> Option<DatumPlaneSingleReferenceBranch> {
3268 const SEPARATOR: [u8; 4] = [0x01, 0x29, 0x01, 0x02];
3269 const SUFFIX: [u8; 35] = [
3270 0x01, 0x01, 0x07, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff,
3271 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3272 0x00, 0x00, 0x00, 0x00, 0x0d,
3273 ];
3274 if let Some(branch) = datum_plane_single_reference_branch(record) {
3275 return Some(branch);
3276 }
3277 let header = datum_plane_payload_header(record)?;
3278 if header.declared_count != 3 || header.branch_tag != 0x28 {
3279 return None;
3280 }
3281 let mut at = 10;
3282 let descriptor_offset = record.payload_offset + at;
3283 let (CompactIndex::Value(descriptor_index), width) = compact_index(record.payload.get(at..)?)?
3284 else {
3285 return None;
3286 };
3287 let raw_descriptor_index = record.payload[at..at + width].to_vec();
3288 at += width;
3289 (record.payload.get(at..at + SEPARATOR.len()) == Some(&SEPARATOR)).then_some(())?;
3290 at += SEPARATOR.len();
3291 let object_offset = record.payload_offset + at;
3292 let (object_index, width) = payload_object_index(record.payload.get(at..)?)?;
3293 let raw_object_index = record.payload[at..at + width].to_vec();
3294 at += width;
3295 (record.payload.get(at..at + SUFFIX.len()) == Some(&SUFFIX)).then_some(())?;
3296 Some(DatumPlaneSingleReferenceBranch {
3297 descriptor_index,
3298 raw_descriptor_index,
3299 descriptor_offset,
3300 object_index,
3301 raw_object_index,
3302 object_offset,
3303 })
3304}
3305
3306pub fn datum_plane_double_reference_branch(
3308 record: OperationRecord<'_>,
3309) -> Option<DatumPlaneDoubleReferenceBranch> {
3310 const COUNT_TWO_MIDDLE: [u8; 11] = [
3311 0x01, 0x01, 0x18, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xff,
3312 ];
3313 const COUNT_TWO_SUFFIX: [u8; 23] = [
3314 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
3315 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d,
3316 ];
3317 const COUNT_THREE_MIDDLE: [u8; 5] = [0x01, 0x01, 0x3a, 0x01, 0x02];
3318 const COUNT_THREE_SUFFIX: [u8; 34] = [
3319 0x01, 0x17, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff,
3320 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3321 0x00, 0x00, 0x00, 0x0d,
3322 ];
3323 let header = datum_plane_payload_header(record)?;
3324 if header.branch_tag != 0x29 || !matches!(header.declared_count, 2 | 3) {
3325 return None;
3326 }
3327 let mut at = 10;
3328 let (first_index, first_width) = payload_object_index(record.payload.get(at..)?)?;
3329 let first = PayloadObjectReference {
3330 offset: record.payload_offset + at,
3331 object_index: first_index,
3332 raw_object_index: record.payload[at..at + first_width].to_vec(),
3333 };
3334 at += first_width;
3335 let middle = if header.declared_count == 2 {
3336 COUNT_TWO_MIDDLE.as_slice()
3337 } else {
3338 COUNT_THREE_MIDDLE.as_slice()
3339 };
3340 (record.payload.get(at..at + middle.len()) == Some(middle)).then_some(())?;
3341 at += middle.len();
3342 let (second_index, second_width) = payload_object_index(record.payload.get(at..)?)?;
3343 let second = PayloadObjectReference {
3344 offset: record.payload_offset + at,
3345 object_index: second_index,
3346 raw_object_index: record.payload[at..at + second_width].to_vec(),
3347 };
3348 at += second_width;
3349 let suffix = if header.declared_count == 2 {
3350 COUNT_TWO_SUFFIX.as_slice()
3351 } else {
3352 COUNT_THREE_SUFFIX.as_slice()
3353 };
3354 (record.payload.get(at..at + suffix.len()) == Some(suffix)).then_some(())?;
3355 Some(DatumPlaneDoubleReferenceBranch {
3356 references: [first, second],
3357 })
3358}
3359
3360pub fn datum_plane_object_index_lanes(bytes: &[u8]) -> Vec<DatumPlaneObjectIndexLane> {
3362 let mut lanes = Vec::new();
3363 for start in 0..bytes.len().saturating_sub(7) {
3364 if bytes[start] != 0x01 {
3365 continue;
3366 }
3367 let declared_count = bytes[start + 1];
3368 if declared_count < 2 {
3369 continue;
3370 }
3371 let mut at = start + 2;
3372 let mut indices = Vec::with_capacity(usize::from(declared_count) - 1);
3373 let mut raw_indices = Vec::with_capacity(usize::from(declared_count) - 1);
3374 let mut complete = true;
3375 for _ in 1..declared_count {
3376 let Some((CompactIndex::Value(value), width)) = bytes.get(at..).and_then(compact_index)
3377 else {
3378 complete = false;
3379 break;
3380 };
3381 indices.push((value, at));
3382 raw_indices.push(bytes[at..at + width].to_vec());
3383 at += width;
3384 }
3385 if !complete || bytes.get(at) != Some(&0x00) || at + 5 != bytes.len() {
3386 continue;
3387 }
3388 let trailer = u32::from_be_bytes(bytes[at + 1..at + 5].try_into().expect("four bytes"));
3389 lanes.push(DatumPlaneObjectIndexLane {
3390 offset: start,
3391 declared_count,
3392 indices,
3393 raw_indices,
3394 trailer,
3395 });
3396 }
3397 lanes
3398}
3399
3400pub fn datum_plane_object_scalar_pairs(bytes: &[u8]) -> Vec<DatumPlaneObjectScalarPair> {
3402 const DISCRIMINATOR: [u8; 18] = [
3403 0x6d, 0x00, 0xf0, 0x08, 0x02, 0x03, 0x01, 0x03, 0x01, 0xc0, 0x45, 0x04, 0x00, 0x80, 0x86,
3404 0x02, 0x00, 0x03,
3405 ];
3406 bytes
3407 .windows(DISCRIMINATOR.len())
3408 .enumerate()
3409 .filter_map(|(offset, window)| {
3410 (window == DISCRIMINATOR).then_some(())?;
3411 let first = offset + DISCRIMINATOR.len();
3412 let second = first + 9;
3413 (bytes.get(first + 8) == Some(&0x00)).then_some(())?;
3414 Some(DatumPlaneObjectScalarPair {
3415 offset,
3416 values: [
3417 shifted_ieee_f64(bytes.get(first..first + 8)?)?,
3418 shifted_ieee_f64(bytes.get(second..second + 8)?)?,
3419 ],
3420 raw_values: [
3421 bytes.get(first..first + 8)?.try_into().ok()?,
3422 bytes.get(second..second + 8)?.try_into().ok()?,
3423 ],
3424 value_offsets: [first, second],
3425 })
3426 })
3427 .collect()
3428}
3429
3430pub fn datum_plane_descriptor_block(bytes: &[u8]) -> Option<DatumPlaneDescriptorBlock> {
3432 if bytes.len() != 40 {
3433 return None;
3434 }
3435 let delimiter = bytes.iter().position(|byte| *byte == b'?')?;
3436 let identity = bytes.get(..delimiter)?;
3437 if identity.is_empty()
3438 || !identity
3439 .iter()
3440 .all(|byte| byte.is_ascii_digit() || (b'a'..=b'f').contains(byte))
3441 {
3442 return None;
3443 }
3444 let suffix = bytes.get(delimiter..)?;
3445 if suffix.get(..2) != Some(b"?A") {
3446 return None;
3447 }
3448 let (CompactIndex::Value(schema_index), width) = compact_index(suffix.get(2..)?)? else {
3449 return None;
3450 };
3451 let label_start = 2 + width + 3;
3452 if suffix.get(2 + width..label_start) != Some(&[0xff, 0x02, 0x01]) {
3453 return None;
3454 }
3455 let label = suffix.get(label_start..)?;
3456 if label.is_empty() || !label.iter().all(u8::is_ascii_graphic) {
3457 return None;
3458 }
3459 Some(DatumPlaneDescriptorBlock {
3460 identity: std::str::from_utf8(identity).ok()?.to_string(),
3461 suffix: suffix.to_vec(),
3462 schema_index,
3463 label: std::str::from_utf8(label).ok()?.to_string(),
3464 })
3465}
3466
3467pub fn object_payload_scalar_pairs(bytes: &[u8]) -> Vec<ObjectPayloadScalarPair> {
3469 const SHORT: [u8; 15] = [
3470 0x08, 0x02, 0x03, 0x01, 0x03, 0x01, 0xc0, 0x45, 0x04, 0x00, 0x80, 0x86, 0x02, 0x00, 0x03,
3471 ];
3472 const EXTENDED: [u8; 16] = [
3473 0x08, 0x02, 0x03, 0x01, 0x81, 0x02, 0x01, 0xc0, 0x45, 0x04, 0x00, 0x80, 0x86, 0x02, 0x00,
3474 0x03,
3475 ];
3476 let mut pairs = Vec::new();
3477 for discriminator in [SHORT.as_slice(), EXTENDED.as_slice()] {
3478 for (offset, window) in bytes.windows(discriminator.len()).enumerate() {
3479 if window != discriminator {
3480 continue;
3481 }
3482 let first = offset + discriminator.len();
3483 let second = first + 9;
3484 if bytes.get(first + 8) != Some(&0x00) {
3485 continue;
3486 }
3487 let Some(raw_values) = bytes
3488 .get(first..first + 8)
3489 .and_then(|value| <[u8; 8]>::try_from(value).ok())
3490 .zip(
3491 bytes
3492 .get(second..second + 8)
3493 .and_then(|value| <[u8; 8]>::try_from(value).ok()),
3494 )
3495 .map(|(first, second)| [first, second])
3496 else {
3497 continue;
3498 };
3499 let Some(values) = shifted_ieee_f64(&raw_values[0])
3500 .zip(shifted_ieee_f64(&raw_values[1]))
3501 .map(|(first, second)| [first, second])
3502 else {
3503 continue;
3504 };
3505 pairs.push(ObjectPayloadScalarPair {
3506 offset,
3507 values,
3508 raw_values,
3509 value_offsets: [first, second],
3510 discriminator: discriminator.to_vec(),
3511 });
3512 }
3513 }
3514 pairs.sort_by_key(|pair| pair.offset);
3515 pairs
3516}
3517
3518pub fn sketch_payload_fixed_pairs(bytes: &[u8]) -> Vec<SketchPayloadFixedPair> {
3520 const DISCRIMINATOR: [u8; 8] = [0x04, 0xe0, 0x48, 0x0e, 0x02, 0x03, 0x80, 0x84];
3521 let mut pairs = Vec::new();
3522 for (offset, window) in bytes.windows(DISCRIMINATOR.len()).enumerate() {
3523 if window != DISCRIMINATOR {
3524 continue;
3525 }
3526 let first = offset + DISCRIMINATOR.len();
3527 let second = first + 9;
3528 if bytes.get(first) != Some(&0x30)
3529 || bytes.get(first + 8) != Some(&0x00)
3530 || bytes.get(second) != Some(&0x30)
3531 {
3532 continue;
3533 }
3534 let Some(first_raw) = bytes
3535 .get(first + 1..first + 8)
3536 .and_then(|raw| raw.try_into().ok())
3537 else {
3538 continue;
3539 };
3540 let Some(second_raw) = bytes
3541 .get(second + 1..second + 8)
3542 .and_then(|raw| raw.try_into().ok())
3543 else {
3544 continue;
3545 };
3546 pairs.push(SketchPayloadFixedPair {
3547 offset,
3548 values: [decode_q1_55(first_raw), decode_q1_55(second_raw)],
3549 value_offsets: [first, second],
3550 raw_values: [first_raw, second_raw],
3551 });
3552 }
3553 pairs
3554}
3555
3556pub fn datum_csys_payload_fixed_pairs(bytes: &[u8]) -> Vec<DatumCsysPayloadFixedPair> {
3558 const DISCRIMINATOR: [u8; 15] = [
3559 0x0b, 0x02, 0x03, 0x01, 0x03, 0x01, 0xc0, 0x45, 0x04, 0x00, 0x80, 0x86, 0x02, 0x00, 0x03,
3560 ];
3561 let mut pairs = Vec::new();
3562 for (offset, window) in bytes.windows(DISCRIMINATOR.len()).enumerate() {
3563 if window != DISCRIMINATOR {
3564 continue;
3565 }
3566 let first = offset + DISCRIMINATOR.len();
3567 let second = first + 9;
3568 if bytes.get(first) != Some(&0x30)
3569 || bytes.get(first + 8) != Some(&0x00)
3570 || bytes.get(second) != Some(&0x30)
3571 {
3572 continue;
3573 }
3574 let Some(first_raw) = bytes
3575 .get(first + 1..first + 8)
3576 .and_then(|raw| raw.try_into().ok())
3577 else {
3578 continue;
3579 };
3580 let Some(second_raw) = bytes
3581 .get(second + 1..second + 8)
3582 .and_then(|raw| raw.try_into().ok())
3583 else {
3584 continue;
3585 };
3586 pairs.push(DatumCsysPayloadFixedPair {
3587 offset,
3588 values: [decode_q1_55(first_raw), decode_q1_55(second_raw)],
3589 value_offsets: [first, second],
3590 raw_values: [first_raw, second_raw],
3591 discriminator: DISCRIMINATOR.to_vec(),
3592 });
3593 }
3594 pairs
3595}
3596
3597fn decode_q1_55(raw: [u8; 7]) -> f64 {
3598 let unsigned = raw
3599 .into_iter()
3600 .fold(0_u64, |value, byte| (value << 8) | u64::from(byte));
3601 let signed = if unsigned & (1_u64 << 55) == 0 {
3602 unsigned as i64
3603 } else {
3604 (unsigned as i64) - (1_i64 << 56)
3605 };
3606 signed as f64 / (1_u64 << 55) as f64
3607}
3608
3609pub fn draft_construction_fixed_lanes(bytes: &[u8]) -> Vec<DraftConstructionFixedLane> {
3611 const DISCRIMINATOR: [u8; 18] = [
3612 0x25, 0x25, 0x41, 0x00, 0x04, 0x01, 0x07, 0x01, 0xc0, 0x45, 0x10, 0x00, 0x80, 0x86, 0x02,
3613 0x00, 0x01, 0x00,
3614 ];
3615 bytes
3616 .windows(DISCRIMINATOR.len())
3617 .enumerate()
3618 .filter_map(|(offset, window)| {
3619 (window == DISCRIMINATOR).then_some(())?;
3620 let mut at = offset + DISCRIMINATOR.len();
3621 let mut markers = Vec::new();
3622 let mut raw_values = Vec::new();
3623 let mut value_offsets = Vec::new();
3624 while matches!(bytes.get(at), Some(0x30 | 0xb0)) {
3625 let raw = bytes.get(at + 1..at + 8)?.try_into().ok()?;
3626 markers.push(bytes[at]);
3627 raw_values.push(raw);
3628 value_offsets.push(at);
3629 at += 8;
3630 }
3631 if raw_values.is_empty() || bytes.get(at) != Some(&0x00) {
3632 return None;
3633 }
3634 let values = raw_values.iter().copied().map(decode_q1_55).collect();
3635 Some(DraftConstructionFixedLane {
3636 offset,
3637 values,
3638 markers,
3639 raw_values,
3640 value_offsets,
3641 })
3642 })
3643 .collect()
3644}
3645
3646pub fn draft_construction_binary32_lanes(bytes: &[u8]) -> Vec<DraftConstructionBinary32Lane> {
3648 const BRANCH_04: [u8; 18] = [
3649 0x90, 0x18, 0x45, 0x01, 0x04, 0x01, 0x04, 0x01, 0xc0, 0x45, 0x04, 0x04, 0x80, 0x86, 0x02,
3650 0x00, 0x03, 0x00,
3651 ];
3652 const BRANCH_03: [u8; 18] = [
3653 0x90, 0x18, 0x45, 0x01, 0x04, 0x01, 0x03, 0x01, 0xc0, 0x45, 0x04, 0x00, 0x80, 0x86, 0x02,
3654 0x00, 0x03, 0x00,
3655 ];
3656 let mut lanes = [BRANCH_04, BRANCH_03]
3657 .into_iter()
3658 .flat_map(|discriminator| {
3659 bytes
3660 .windows(discriminator.len())
3661 .enumerate()
3662 .filter_map(move |(offset, window)| {
3663 (window == discriminator).then_some(())?;
3664 let mut at = offset + discriminator.len();
3665 let mut values = Vec::new();
3666 let mut raw_values = Vec::new();
3667 let mut value_offsets = Vec::new();
3668 while matches!(bytes.get(at), Some(0x40..=0x5f | 0xc0..=0xdf)) {
3669 let raw: [u8; 4] = bytes.get(at..at + 4)?.try_into().ok()?;
3670 let Some((value, PayloadScalarEncoding::Binary32, 4)) =
3671 payload_scalar(&raw)
3672 else {
3673 return None;
3674 };
3675 values.push(value);
3676 raw_values.push(raw);
3677 value_offsets.push(at);
3678 at += 4;
3679 }
3680 if values.is_empty() || bytes.get(at) != Some(&0x00) {
3681 return None;
3682 }
3683 Some(DraftConstructionBinary32Lane {
3684 offset,
3685 discriminator,
3686 branch: discriminator[6],
3687 values,
3688 raw_values,
3689 value_offsets,
3690 })
3691 })
3692 .collect::<Vec<_>>()
3693 })
3694 .collect::<Vec<_>>();
3695 lanes.sort_by_key(|lane| lane.offset);
3696 lanes
3697}
3698
3699pub fn datum_csys_descriptor_block(bytes: &[u8]) -> Option<DatumCsysDescriptorBlock> {
3701 let mut matches = Vec::new();
3702 let mut at = 0;
3703 while at < bytes.len() {
3704 if !(bytes[at].is_ascii_digit() || (b'a'..=b'f').contains(&bytes[at])) {
3705 at += 1;
3706 continue;
3707 }
3708 let start = at;
3709 while at < bytes.len() && (bytes[at].is_ascii_digit() || (b'a'..=b'f').contains(&bytes[at]))
3710 {
3711 at += 1;
3712 }
3713 if (30..=32).contains(&(at - start)) {
3714 matches.push((start, at));
3715 }
3716 }
3717 let [(start, end)] = matches.as_slice() else {
3718 return None;
3719 };
3720 Some(DatumCsysDescriptorBlock {
3721 prefix: bytes[..*start].to_vec(),
3722 identity: std::str::from_utf8(&bytes[*start..*end]).ok()?.to_string(),
3723 suffix: bytes[*end..].to_vec(),
3724 identity_offset: *start,
3725 })
3726}
3727
3728pub fn draft_construction_identity_frames(bytes: &[u8]) -> Vec<DraftConstructionIdentityFrame> {
3730 let mut frames = Vec::new();
3731 for offset in 0..bytes.len() {
3732 if bytes[offset] != 0x41 {
3733 continue;
3734 }
3735 let Some((prefix_len, form)) = draft_identity_prefix(&bytes[offset..]) else {
3736 continue;
3737 };
3738 let identity_start = offset + prefix_len;
3739 let mut identity_end = identity_start;
3740 while bytes
3741 .get(identity_end)
3742 .is_some_and(|byte| byte.is_ascii_digit() || (b'a'..=b'f').contains(byte))
3743 {
3744 identity_end += 1;
3745 }
3746 if identity_end == identity_start || bytes.get(identity_end) != Some(&b'?') {
3747 continue;
3748 }
3749 frames.push(DraftConstructionIdentityFrame {
3750 offset,
3751 prefix: bytes[offset..offset + prefix_len].to_vec(),
3752 form,
3753 identity: String::from_utf8(bytes[identity_start..identity_end].to_vec())
3754 .expect("lowercase hexadecimal bytes are UTF-8"),
3755 identity_offset: identity_start,
3756 });
3757 }
3758 frames
3759}
3760
3761fn draft_identity_prefix(bytes: &[u8]) -> Option<(usize, DraftConstructionIdentityFrameForm)> {
3762 if bytes.first() != Some(&0x41) {
3763 return None;
3764 }
3765 if bytes.get(1) == Some(&0xf0) {
3766 let (index, index_width) = compact_index(bytes.get(2..)?)?;
3767 let end = 2 + index_width + 3;
3768 (bytes.get(2 + index_width..end) == Some(&[0xff, 0x02, 0x01])).then_some((
3769 end,
3770 DraftConstructionIdentityFrameForm::Tagged {
3771 index: compact_index_value(index),
3772 },
3773 ))
3774 } else {
3775 let (CompactIndex::Value(first_index), first_width) = compact_index(bytes.get(1..)?)?
3776 else {
3777 return None;
3778 };
3779 let second_at = 1 + first_width + 1;
3780 if bytes.get(1 + first_width) != Some(&0xf0) {
3781 return None;
3782 }
3783 let (second_index, second_width) = compact_index(bytes.get(second_at..)?)?;
3784 let branch_at = second_at + second_width;
3785 let end = branch_at + 2;
3786 (matches!(bytes.get(branch_at), Some(0x02 | 0x03))
3787 && bytes.get(branch_at + 1) == Some(&0x01))
3788 .then_some((
3789 end,
3790 DraftConstructionIdentityFrameForm::IndexedBranch {
3791 first_index,
3792 second_index: compact_index_value(second_index),
3793 branch: bytes[branch_at],
3794 },
3795 ))
3796 }
3797}
3798
3799fn compact_index_value(index: CompactIndex) -> Option<u32> {
3800 match index {
3801 CompactIndex::Null => None,
3802 CompactIndex::Value(value) => Some(value),
3803 }
3804}
3805
3806pub fn data_block_object_frames(bytes: &[u8]) -> Vec<DataBlockObjectFrame> {
3808 const DISCRIMINATOR: [u8; 18] = [
3809 0x00, 0x72, 0x01, 0xc0, 0x20, 0x02, 0x01, 0xc0, 0x45, 0x04, 0x00, 0x80, 0x86, 0x02, 0x01,
3810 0x02, 0x80, 0xa4,
3811 ];
3812 let mut references = Vec::new();
3813 let mut offset = 0;
3814 while offset < bytes.len() {
3815 let Some((CompactIndex::Value(object_id), width)) = compact_index(&bytes[offset..]) else {
3816 offset += 1;
3817 continue;
3818 };
3819 if bytes.get(offset + width..offset + width + DISCRIMINATOR.len()) != Some(&DISCRIMINATOR) {
3820 offset += 1;
3821 continue;
3822 }
3823 references.push(DataBlockObjectFrame {
3824 object_id,
3825 raw_object_id: bytes[offset..offset + width].to_vec(),
3826 offset,
3827 });
3828 offset += width + DISCRIMINATOR.len();
3829 }
3830 references
3831}
3832
3833fn counted_u32_atoms(bytes: &[u8], at: &mut usize) -> Option<(Vec<u32>, Vec<usize>)> {
3834 if bytes.get(*at) != Some(&0x01) {
3835 return None;
3836 }
3837 let count = usize::from(*bytes.get(*at + 1)?);
3838 if count < 2 {
3839 return None;
3840 }
3841 *at += 2;
3842 let mut values = Vec::with_capacity(count - 1);
3843 let mut offsets = Vec::with_capacity(count - 1);
3844 for _ in 1..count {
3845 offsets.push(*at);
3846 values.push(u32::from_be_bytes(
3847 bytes.get(*at..*at + 4)?.try_into().ok()?,
3848 ));
3849 *at += 4;
3850 }
3851 Some((values, offsets))
3852}
3853
3854struct CountedCompactValues {
3855 values: Vec<u32>,
3856 raw_values: Vec<Vec<u8>>,
3857 offsets: Vec<usize>,
3858}
3859
3860fn counted_compact_values(bytes: &[u8], at: &mut usize) -> Option<CountedCompactValues> {
3861 if bytes.get(*at) != Some(&0x01) {
3862 return None;
3863 }
3864 let count = usize::from(*bytes.get(*at + 1)?);
3865 if count < 2 {
3866 return None;
3867 }
3868 *at += 2;
3869 let mut values = Vec::with_capacity(count - 1);
3870 let mut raw_values = Vec::with_capacity(count - 1);
3871 let mut offsets = Vec::with_capacity(count - 1);
3872 for _ in 1..count {
3873 let value_at = *at;
3874 let (value, width) = compact_index(bytes.get(*at..)?)?;
3875 let CompactIndex::Value(value) = value else {
3876 return None;
3877 };
3878 values.push(value);
3879 raw_values.push(bytes[value_at..value_at + width].to_vec());
3880 offsets.push(value_at);
3881 *at += width;
3882 }
3883 Some(CountedCompactValues {
3884 values,
3885 raw_values,
3886 offsets,
3887 })
3888}
3889
3890fn payload_scalar(bytes: &[u8]) -> Option<(f64, PayloadScalarEncoding, usize)> {
3891 let marker = *bytes.first()?;
3892 match marker {
3893 0x00 => Some((0.0, PayloadScalarEncoding::Zero, 1)),
3894 0x20..=0x3f | 0xa0..=0xbf => Some((
3895 shifted_ieee_f64(bytes.get(..8)?)?,
3896 PayloadScalarEncoding::Binary64,
3897 8,
3898 )),
3899 0x40..=0x5f | 0xc0..=0xdf => {
3900 let encoded: [u8; 4] = bytes.get(..4)?.try_into().ok()?;
3901 let mut raw = encoded;
3902 raw[0] = raw[0].checked_sub(0x10)?;
3903 let value = f32::from_be_bytes(raw);
3904 value
3905 .is_finite()
3906 .then_some((f64::from(value), PayloadScalarEncoding::Binary32, 4))
3907 }
3908 _ => None,
3909 }
3910}
3911
3912fn extrude_profile_reference_field(
3913 record: OperationRecord<'_>,
3914 start: usize,
3915) -> Option<ExtrudeProfileReferenceField> {
3916 let count = *record.payload.get(start + 4)?;
3917 if count < 2 {
3918 return None;
3919 }
3920 let references_start = start + 5;
3921 let mut at = references_start;
3922 let mut references = Vec::with_capacity(usize::from(count - 1));
3923 for _ in 1..count {
3924 let (object_index, width) = payload_object_index(record.payload.get(at..)?)?;
3925 references.push(PayloadObjectReference {
3926 offset: record.payload_offset + at,
3927 object_index,
3928 raw_object_index: record.payload[at..at + width].to_vec(),
3929 });
3930 at += width;
3931 }
3932 if record.payload.get(at..at + 3) != Some(&[0x01, 0x03, 0x79]) {
3933 return None;
3934 }
3935 let encoded_references = record.payload.get(references_start..at)?;
3936 let witness_len = 2 + encoded_references.len() + 2;
3937 let witness_count = record
3938 .payload
3939 .windows(witness_len)
3940 .filter(|candidate| {
3941 candidate.starts_with(&[0x01, count])
3942 && candidate.get(2..2 + encoded_references.len()) == Some(encoded_references)
3943 && candidate.ends_with(&[0x00, 0x00])
3944 })
3945 .count();
3946 Some(ExtrudeProfileReferenceField {
3947 references,
3948 witnessed: witness_count == 1,
3949 })
3950}
3951
3952pub fn expression_declaration_name(bytes: &[u8]) -> Option<ExpressionDeclarationName<'_>> {
3954 let mut matches = Vec::new();
3955 let mut literals = Vec::new();
3956 for at in 0..bytes.len().saturating_sub(4) {
3957 if bytes[at] != 0x04 {
3958 continue;
3959 }
3960 let declared = usize::from(bytes[at + 1]);
3961 if declared < 4 {
3962 continue;
3963 }
3964 let Some(end) = at.checked_add(declared) else {
3965 continue;
3966 };
3967 let Some(raw) = bytes.get(at + 2..end) else {
3968 continue;
3969 };
3970 if bytes.get(end) != Some(&0) {
3971 continue;
3972 }
3973 let Ok(value) = std::str::from_utf8(raw) else {
3974 continue;
3975 };
3976 let Some((parameter_index, qualifier)) = parameter_name_parts(value) else {
3977 if evaluate_constant_expression(value).is_some() {
3978 literals.push(value);
3979 }
3980 continue;
3981 };
3982 matches.push(ExpressionDeclarationName {
3983 offset: at,
3984 value,
3985 parameter_index,
3986 qualifier,
3987 literal: None,
3988 });
3989 }
3990 let [declaration] = matches.as_slice() else {
3991 return None;
3992 };
3993 let literal = match literals.as_slice() {
3994 [literal] => Some(*literal),
3995 _ => None,
3996 };
3997 Some(ExpressionDeclarationName {
3998 literal,
3999 ..*declaration
4000 })
4001}
4002
4003pub fn operation_body_reference(record: OperationRecord<'_>) -> Option<OperationBodyReference> {
4005 let matches = operation_body_references(record);
4006 let [reference] = matches.as_slice() else {
4007 return None;
4008 };
4009 Some(reference.clone())
4010}
4011
4012pub fn operation_body_references(record: OperationRecord<'_>) -> Vec<OperationBodyReference> {
4014 let mut matches = Vec::new();
4015 for marker in record
4016 .bytes
4017 .windows(3)
4018 .enumerate()
4019 .filter_map(|(offset, window)| (window == [0x01, 0x02, 0x10]).then_some(offset))
4020 {
4021 let token = marker + 3;
4022 let Some((Some(object_index), end)) = feature_object_index(record.bytes, token) else {
4023 continue;
4024 };
4025 if record.bytes.get(end) == Some(&0xff) {
4026 matches.push(OperationBodyReference {
4027 offset: record.offset + token,
4028 object_index,
4029 raw_object_index: record.bytes[token..end].to_vec(),
4030 });
4031 }
4032 }
4033 matches
4034}
4035
4036fn feature_object_index(bytes: &[u8], at: usize) -> Option<(Option<u32>, usize)> {
4037 let prefix = *bytes.get(at)?;
4038 match prefix {
4039 0x00..=0x7f => Some((Some(u32::from(prefix)), at + 1)),
4040 0x80..=0x8f => Some((
4041 Some(u32::from(prefix - 0x80) * 256 + u32::from(*bytes.get(at + 1)?)),
4042 at + 2,
4043 )),
4044 0x90 => Some((
4045 Some(u32::from(u16::from_be_bytes([
4046 *bytes.get(at + 1)?,
4047 *bytes.get(at + 2)?,
4048 ]))),
4049 at + 3,
4050 )),
4051 0xff => Some((None, at + 1)),
4052 _ => None,
4053 }
4054}
4055
4056pub fn data_block_object_references(bytes: &[u8]) -> Vec<DataBlockObjectReference> {
4058 let mut references = Vec::new();
4059 let mut at = 0usize;
4060 while at + 5 <= bytes.len() {
4061 if bytes.get(at..at + 2) != Some(&[0x04, 0x00]) {
4062 at += 1;
4063 continue;
4064 }
4065 let token = at + 2;
4066 let Some((Some(object_index), end)) = feature_object_index(bytes, token) else {
4067 at += 1;
4068 continue;
4069 };
4070 if bytes.get(end..end + 2) != Some(&[0x02, 0x0b]) {
4071 at += 1;
4072 continue;
4073 }
4074 references.push(DataBlockObjectReference {
4075 offset: token,
4076 object_index,
4077 raw_object_index: bytes[token..end].to_vec(),
4078 });
4079 at = end + 2;
4080 }
4081 references
4082}
4083
4084pub fn boolean_operations(bytes: &[u8], base_offset: usize) -> Vec<BooleanOperation> {
4086 const BODY_HEADER: &[u8] = &[
4087 0x31, 0x00, 0x00, 0x01, 0x00, 0x14, 0x2f, 0xa4, 0x7a, 0xe1, 0x47, 0xae, 0x14, 0x7b, 0x03,
4088 0x00, 0x00, 0xe0, 0x7f, 0xff, 0xff, 0xff, 0x01, 0x01,
4089 ];
4090 operation_labels(bytes, base_offset)
4091 .into_iter()
4092 .filter_map(|label| {
4093 let kind = match label.value {
4094 "UNITE" => BooleanOperationKind::Unite,
4095 "SUBTRACT" => BooleanOperationKind::Subtract,
4096 "INTERSECT" => BooleanOperationKind::Intersect,
4097 _ => return None,
4098 };
4099 let at = label.offset.checked_sub(base_offset)?;
4100 let label_end = at.checked_add(usize::from(*bytes.get(at + 1)?))? + 1;
4101 if bytes.get(label_end..label_end + BODY_HEADER.len()) != Some(BODY_HEADER) {
4102 return None;
4103 }
4104 let (targets, next) =
4105 counted_feature_object_indices(bytes, base_offset, label_end + BODY_HEADER.len())?;
4106 if targets.len() != 1 || bytes.get(next) != Some(&0) {
4107 return None;
4108 }
4109 let (tools, end) = counted_feature_object_indices(bytes, base_offset, next + 1)?;
4110 if tools.is_empty() || bytes.get(end) != Some(&0) {
4111 return None;
4112 }
4113 let target = targets.into_iter().next()?;
4114 Some(BooleanOperation {
4115 offset: label.offset,
4116 kind,
4117 target: target.object_index,
4118 raw_target: target.raw_object_index,
4119 target_offset: target.offset,
4120 tools: tools.iter().map(|tool| tool.object_index).collect(),
4121 raw_tools: tools
4122 .iter()
4123 .map(|tool| tool.raw_object_index.clone())
4124 .collect(),
4125 tool_offsets: tools.iter().map(|tool| tool.offset).collect(),
4126 })
4127 })
4128 .collect()
4129}
4130
4131fn counted_feature_object_indices(
4132 bytes: &[u8],
4133 base_offset: usize,
4134 at: usize,
4135) -> Option<(Vec<PayloadObjectReference>, usize)> {
4136 if bytes.get(at) != Some(&0x01) {
4137 return None;
4138 }
4139 let count = usize::from(*bytes.get(at + 1)?).checked_sub(1)?;
4140 let mut cursor = at + 2;
4141 let mut values = Vec::with_capacity(count);
4142 for _ in 0..count {
4143 let (value, next) = feature_object_index(bytes, cursor)?;
4144 values.push(PayloadObjectReference {
4145 offset: base_offset + cursor,
4146 object_index: value?,
4147 raw_object_index: bytes.get(cursor..next)?.to_vec(),
4148 });
4149 cursor = next;
4150 }
4151 Some((values, cursor))
4152}
4153
4154pub fn counted_record_references(
4156 bytes: &[u8],
4157 base_offset: usize,
4158 record_count: usize,
4159) -> Vec<ReferenceValue> {
4160 let mut references = Vec::new();
4161 let mut at = 0usize;
4162 while at + 5 <= bytes.len() {
4163 if bytes[at] != 0x01 || bytes[at + 1] < 2 {
4164 at += 1;
4165 continue;
4166 }
4167 let count = usize::from(bytes[at + 1] - 1);
4168 let Some(end) = at.checked_add(2 + count * 3) else {
4169 at += 1;
4170 continue;
4171 };
4172 if end > bytes.len() || (0..count).any(|index| bytes[at + 2 + index * 3] != 0x90) {
4173 at += 1;
4174 continue;
4175 }
4176 let mut run = Vec::with_capacity(count);
4177 for index in 0..count {
4178 let token = at + 2 + index * 3;
4179 let value = u16::from_be_bytes([bytes[token + 1], bytes[token + 2]]);
4180 if usize::from(value) >= record_count {
4181 run.clear();
4182 break;
4183 }
4184 run.push(ReferenceValue {
4185 offset: base_offset + token,
4186 kind: ReferenceKind::RecordOrdinal16,
4187 value: u32::from(value),
4188 });
4189 }
4190 if run.is_empty() {
4191 at += 1;
4192 } else {
4193 references.extend(run);
4194 at = end;
4195 }
4196 }
4197 references
4198}
4199
4200pub fn record_references(bytes: &[u8], base_offset: usize) -> Vec<ReferenceValue> {
4202 let mut out = references(bytes, base_offset)
4203 .into_iter()
4204 .filter(|reference| reference.kind == ReferenceKind::PersistentHandle)
4205 .collect::<Vec<_>>();
4206 out.extend(
4207 dense_reference_suffix(bytes, base_offset)
4208 .into_iter()
4209 .filter(|reference| reference.kind == ReferenceKind::Tagged28),
4210 );
4211 out.sort_by_key(|reference| reference.offset);
4212 out
4213}
4214
4215pub fn references(bytes: &[u8], base_offset: usize) -> Vec<ReferenceValue> {
4217 let mut out = Vec::new();
4218 let mut at = 0usize;
4219 while at < bytes.len() {
4220 if bytes[at] == 0xe0 {
4221 if let Some(raw) = bytes
4222 .get(at + 1..at + 5)
4223 .and_then(|raw| raw.try_into().ok())
4224 {
4225 out.push(ReferenceValue {
4226 offset: base_offset + at,
4227 kind: ReferenceKind::PersistentHandle,
4228 value: u32::from_be_bytes(raw),
4229 });
4230 at += 5;
4231 continue;
4232 }
4233 } else if bytes[at] & 0xf0 == 0xc0 {
4234 if let Some(raw) = bytes.get(at..at + 4).and_then(|raw| raw.try_into().ok()) {
4235 out.push(ReferenceValue {
4236 offset: base_offset + at,
4237 kind: ReferenceKind::Tagged28,
4238 value: u32::from_be_bytes(raw) & 0x0fff_ffff,
4239 });
4240 at += 4;
4241 continue;
4242 }
4243 }
4244 at += 1;
4245 }
4246 out
4247}
4248
4249pub fn dense_reference_suffix(bytes: &[u8], base_offset: usize) -> Vec<ReferenceValue> {
4255 let references = references(bytes, 0);
4256 for (index, first) in references.iter().enumerate() {
4257 let suffix = &references[index..];
4258 let persistent = suffix
4259 .iter()
4260 .filter(|reference| reference.kind == ReferenceKind::PersistentHandle)
4261 .count();
4262 if persistent < 8 {
4263 continue;
4264 }
4265 let covered = suffix
4266 .iter()
4267 .map(|reference| match reference.kind {
4268 ReferenceKind::PersistentHandle => 5,
4269 ReferenceKind::Tagged28 => 4,
4270 ReferenceKind::RecordOrdinal16 => 3,
4271 })
4272 .sum::<usize>();
4273 let span = bytes.len().saturating_sub(first.offset);
4274 if covered * 10 >= span * 9 {
4275 return suffix
4276 .iter()
4277 .map(|reference| ReferenceValue {
4278 offset: base_offset + reference.offset,
4279 ..*reference
4280 })
4281 .collect();
4282 }
4283 }
4284 Vec::new()
4285}
4286
4287pub fn string_values(bytes: &[u8], base_offset: usize) -> Vec<StringValue<'_>> {
4289 const MARKER: &[u8] = &[0x66, 0x32, 0x03];
4290 bytes
4291 .windows(MARKER.len())
4292 .enumerate()
4293 .filter(|(_, window)| *window == MARKER)
4294 .filter_map(|(offset, _)| {
4295 let declared = usize::from(*bytes.get(offset + 3)?);
4296 let text_len = declared.checked_sub(2)?;
4297 let start = offset.checked_add(4)?;
4298 let end = start.checked_add(text_len)?;
4299 let raw = bytes.get(start..end)?;
4300 (!raw.is_empty()
4301 && raw
4302 .iter()
4303 .all(|byte| byte.is_ascii_graphic() || *byte == b' ')
4304 && bytes.get(end) == Some(&0))
4305 .then(|| StringValue {
4306 offset: base_offset + offset,
4307 value: std::str::from_utf8(raw).expect("invariant: printable ASCII is valid UTF-8"),
4308 })
4309 })
4310 .collect()
4311}
4312
4313pub fn surface_payload_strings(bytes: &[u8]) -> Vec<SurfacePayloadString<'_>> {
4315 const MARKER: &[u8] = &[0x66, 0x1b, 0x03];
4316 bytes
4317 .windows(MARKER.len())
4318 .enumerate()
4319 .filter(|(_, window)| *window == MARKER)
4320 .filter_map(|(offset, _)| {
4321 let text_len = usize::from(*bytes.get(offset + MARKER.len())?);
4322 let start = offset.checked_add(MARKER.len() + 1)?;
4323 let end = start.checked_add(text_len)?;
4324 let raw = bytes.get(start..end)?;
4325 let value = std::str::from_utf8(raw).ok()?;
4326 (!value.is_empty()
4327 && value.chars().all(|character| !character.is_control())
4328 && bytes.get(end) == Some(&0))
4329 .then_some(SurfacePayloadString { offset, value })
4330 })
4331 .collect()
4332}
4333
4334pub fn numeric_expressions(bytes: &[u8]) -> Vec<NumericExpression<'_>> {
4341 if !bytes
4342 .windows(b"hostglobalvariables".len())
4343 .any(|window| window == b"hostglobalvariables")
4344 {
4345 return Vec::new();
4346 }
4347 bytes
4348 .windows(b"(Number [".len())
4349 .enumerate()
4350 .filter(|(_, window)| *window == b"(Number [")
4351 .filter_map(|(offset, _)| {
4352 numeric_expression_at(
4353 &bytes[offset.saturating_sub(3)..],
4354 offset.saturating_sub(3),
4355 None,
4356 )
4357 })
4358 .collect()
4359}
4360
4361pub fn sections(bytes: &[u8]) -> Vec<Section<'_>> {
4363 let mut out = Vec::new();
4364 let mut at = 0usize;
4365 while at + 16 <= bytes.len() {
4366 let Some(relative) = bytes[at..]
4367 .windows(4)
4368 .position(|window| window == [0xff; 4])
4369 else {
4370 break;
4371 };
4372 let offset = at + relative;
4373 let Some(payload_len) = bytes
4374 .get(offset + 8..offset + 12)
4375 .and_then(|raw| raw.try_into().ok())
4376 .map(u32::from_be_bytes)
4377 .map(|value| value as usize)
4378 else {
4379 break;
4380 };
4381 let Some(end) = offset
4382 .checked_add(16)
4383 .and_then(|header_end| header_end.checked_add(payload_len))
4384 else {
4385 at = offset + 4;
4386 continue;
4387 };
4388 if bytes.get(offset + 12..offset + 14) != Some(b"OM") || end > bytes.len() {
4389 at = offset + 4;
4390 continue;
4391 }
4392 let types = type_definitions(bytes, offset + 16, end);
4393 let field_start = types.last().map_or(offset + 16, |definition| {
4394 definition.offset + definition.name.len() + 2
4395 });
4396 let fields = field_definitions(bytes, field_start, end);
4397 let schema_end = fields.last().map_or(field_start, |definition| {
4398 definition.offset + definition.name.len() + 2
4399 });
4400 let record_area_offset = section_record_area_offset(bytes, offset, schema_end, end);
4401 out.push(Section {
4402 offset,
4403 byte_len: end - offset,
4404 types,
4405 fields,
4406 record_area_offset,
4407 record_area: record_area_offset.map(|start| &bytes[start..end]),
4408 });
4409 at = end;
4410 }
4411 out
4412}
4413
4414fn section_record_area_offset(
4415 bytes: &[u8],
4416 section_offset: usize,
4417 schema_end: usize,
4418 section_end: usize,
4419) -> Option<usize> {
4420 let search_end = schema_end.saturating_add(4096).min(section_end);
4421 let mut matches = (schema_end..search_end.saturating_sub(3)).filter_map(|at| {
4422 let relative = usize::try_from(u32_at(bytes, at)?).ok()?;
4423 let target = section_offset.checked_add(relative)?;
4424 (target >= at + 4 && target + 15 <= section_end).then_some(())?;
4425 is_product_record(bytes.get(target + 12..section_end)?).then_some(target)
4426 });
4427 let first = matches.next()?;
4428 matches.next().is_none().then_some(first)
4429}
4430
4431fn is_product_record(bytes: &[u8]) -> bool {
4432 if !matches!(bytes.get(..2), Some([0x04 | 0x05, 0x01])) {
4433 return false;
4434 }
4435 let Some(length) = bytes
4436 .get(2)
4437 .copied()
4438 .map(usize::from)
4439 .and_then(|declared| declared.checked_sub(2))
4440 else {
4441 return false;
4442 };
4443 let Some(end) = 3usize.checked_add(length) else {
4444 return false;
4445 };
4446 bytes.get(3..end).is_some_and(|text| {
4447 text.starts_with(b"NX ")
4448 && text
4449 .iter()
4450 .all(|byte| byte.is_ascii_graphic() || *byte == b' ')
4451 }) && bytes.get(end) == Some(&0)
4452}
4453
4454pub fn indexed_sections(bytes: &[u8]) -> Vec<IndexedSection<'_>> {
4461 let mut out = Vec::new();
4462 let mut seen_record_starts = BTreeSet::new();
4463 for table in 0..bytes.len().saturating_sub(4) {
4464 let Some(count) = u32_at(bytes, table).map(|value| value as usize) else {
4465 continue;
4466 };
4467 if !(2..=100_000).contains(&count) {
4468 continue;
4469 }
4470 let Some(index_len) = count.checked_add(1).and_then(|n| n.checked_mul(4)) else {
4471 continue;
4472 };
4473 let Some(index_start) = table.checked_sub(index_len) else {
4474 continue;
4475 };
4476 let Some(table_end) = count
4477 .checked_mul(4)
4478 .and_then(|length| table.checked_add(4 + length))
4479 else {
4480 continue;
4481 };
4482 if !is_product_record(bytes.get(table_end..).unwrap_or_default())
4483 || u32_at(bytes, index_start) != Some(0)
4484 || !seen_record_starts.insert(table_end)
4485 {
4486 continue;
4487 }
4488 let Some(first) = u32_at(bytes, index_start + 4).map(|value| value as usize) else {
4489 continue;
4490 };
4491 let Some(base) = table_end.checked_sub(first) else {
4492 continue;
4493 };
4494 let mut offsets = Vec::with_capacity(count + 1);
4495 for index in 0..=count {
4496 let Some(value) = u32_at(bytes, index_start + index * 4).map(|v| v as usize) else {
4497 offsets.clear();
4498 break;
4499 };
4500 offsets.push(value);
4501 }
4502 if offsets.len() != count + 1
4503 || offsets[1] == 0
4504 || !offsets.windows(2).all(|pair| pair[0] <= pair[1])
4505 || base
4506 .checked_add(offsets[count])
4507 .is_none_or(|end| end > bytes.len())
4508 {
4509 continue;
4510 }
4511 let mut records = Vec::with_capacity(count - 1);
4512 for index in 1..count {
4513 let start = base + offsets[index];
4514 let end = base + offsets[index + 1];
4515 let Some(payload) = bytes.get(start..end) else {
4516 records.clear();
4517 break;
4518 };
4519 let Some(object_id) = u32_at(bytes, table + 4 + index * 4) else {
4520 records.clear();
4521 break;
4522 };
4523 records.push(EntityRecord {
4524 object_id: Some(object_id),
4525 object_id_offset: Some(table + 4 + index * 4),
4526 offset: start,
4527 bytes: payload,
4528 });
4529 }
4530 if records.len() == count - 1 {
4531 let types = type_definitions(bytes, base, index_start);
4532 let fields = all_field_definitions(bytes, base, index_start);
4533 out.push(IndexedSection {
4534 base,
4535 entity_index_offset: index_start,
4536 object_id_table_offset: table,
4537 types,
4538 fields,
4539 control: None,
4540 column_storage: None,
4541 records,
4542 });
4543 }
4544 }
4545 for count_offset in 8..bytes.len().saturating_sub(4) {
4546 let Some(record_count) = u32_at(bytes, count_offset).map(|value| value as usize) else {
4547 continue;
4548 };
4549 if !(2..=100_000).contains(&record_count) {
4550 continue;
4551 }
4552 let offset_count = record_count + 2;
4553 let Some(index_len) = offset_count.checked_mul(4) else {
4554 continue;
4555 };
4556 let Some(index_start) = count_offset.checked_sub(index_len) else {
4557 continue;
4558 };
4559 let Some(first) = u32_at(bytes, index_start).map(|value| value as usize) else {
4560 continue;
4561 };
4562 let Some(second) = u32_at(bytes, index_start + 4).map(|value| value as usize) else {
4563 continue;
4564 };
4565 let Some(last) = u32_at(bytes, count_offset - 4).map(|value| value as usize) else {
4566 continue;
4567 };
4568 if first < count_offset + 4 || first >= second || second > last || last > bytes.len() {
4569 continue;
4570 }
4571 let mut offsets = Vec::with_capacity(offset_count);
4572 for index in 0..offset_count {
4573 let Some(offset) = u32_at(bytes, index_start + index * 4).map(|v| v as usize) else {
4574 offsets.clear();
4575 break;
4576 };
4577 offsets.push(offset);
4578 }
4579 if offsets.len() != offset_count
4580 || offsets[0] < count_offset + 4
4581 || !offsets.windows(2).all(|pair| pair[0] <= pair[1])
4582 || offsets.last().is_none_or(|end| *end > bytes.len())
4583 {
4584 continue;
4585 }
4586 let product_record_count = root_record_count(&bytes[offsets[0]..offsets[1]])
4587 + root_record_count(&bytes[offsets[1]..offsets[2]]);
4588 if product_record_count != 1 || !seen_record_starts.insert(offsets[1]) {
4589 continue;
4590 }
4591 let records = offsets[1..]
4592 .windows(2)
4593 .map(|bounds| EntityRecord {
4594 object_id: None,
4595 object_id_offset: None,
4596 offset: bounds[0],
4597 bytes: &bytes[bounds[0]..bounds[1]],
4598 })
4599 .collect::<Vec<_>>();
4600 out.push(IndexedSection {
4601 base: 0,
4602 entity_index_offset: index_start,
4603 object_id_table_offset: offsets[0],
4604 types: type_definitions(bytes, 0, index_start),
4605 fields: all_field_definitions(bytes, 0, index_start),
4606 control: Some(EntityRecord {
4607 object_id: None,
4608 object_id_offset: None,
4609 offset: offsets[0],
4610 bytes: &bytes[offsets[0]..offsets[1]],
4611 }),
4612 column_storage: Some(&bytes[offsets[1]..*offsets.last().expect("nonempty offsets")]),
4613 records,
4614 });
4615 }
4616 out
4617}
4618
4619fn root_record_count(bytes: &[u8]) -> usize {
4620 (0..bytes.len())
4621 .filter(|offset| is_product_record(&bytes[*offset..]))
4622 .count()
4623}
4624
4625pub fn store_version(bytes: &[u8], base_offset: usize) -> Option<StoreVersion<'_>> {
4627 (0..bytes.len().saturating_sub(3)).find_map(|at| {
4628 let suffix = &bytes[at..];
4629 is_product_record(suffix).then(|| {
4630 let length = usize::from(suffix[2]) - 2;
4631 StoreVersion {
4632 offset: base_offset + at,
4633 value: std::str::from_utf8(&suffix[3..3 + length])
4634 .expect("validated printable NX version is UTF-8"),
4635 }
4636 })
4637 })
4638}
4639
4640pub fn offset_store_control_values(bytes: &[u8]) -> Option<Vec<u32>> {
4644 (!bytes.is_empty() && bytes.len().is_multiple_of(4)).then_some(())?;
4645 bytes
4646 .chunks_exact(4)
4647 .map(|word| {
4648 (word[0] == 0).then(|| {
4649 u32::from(word[1]) | (u32::from(word[2]) << 8) | (u32::from(word[3]) << 16)
4650 })
4651 })
4652 .collect()
4653}
4654
4655pub fn offset_store_control_class_ordinals(bytes: &[u8], class_count: usize) -> Option<Vec<u32>> {
4658 (class_count > 0).then_some(())?;
4659 let values = offset_store_control_values(bytes)?;
4660 let boundary = values
4661 .iter()
4662 .position(|value| usize::try_from(*value).map_or(true, |value| value >= class_count))?;
4663 (boundary > 0
4664 && values[boundary..]
4665 .iter()
4666 .all(|value| usize::try_from(*value).map_or(true, |value| value >= class_count)))
4667 .then_some(())?;
4668 let ordinals = values[..boundary].to_vec();
4669 let distinct = ordinals.iter().copied().collect::<BTreeSet<_>>();
4670 (distinct.len() == ordinals.len()).then_some(ordinals)
4671}
4672
4673pub fn offset_store_index_values(bytes: &[u8]) -> Option<(usize, Vec<u32>)> {
4675 let matches = (0..bytes.len())
4676 .filter(|offset| is_product_record(&bytes[*offset..]))
4677 .collect::<Vec<_>>();
4678 let [product_offset] = matches.as_slice() else {
4679 return None;
4680 };
4681 let prefix_len = (0..=3).find(|prefix_len| {
4682 *product_offset > *prefix_len
4683 && (*product_offset - *prefix_len).is_multiple_of(4)
4684 && bytes[..*prefix_len].iter().all(|byte| *byte == 0)
4685 })?;
4686 let values = bytes[prefix_len..*product_offset]
4687 .chunks_exact(4)
4688 .map(|word| u32::from_le_bytes(word.try_into().expect("four-byte chunk")))
4689 .collect();
4690 Some((prefix_len, values))
4691}
4692
4693fn type_definitions(bytes: &[u8], start: usize, end: usize) -> Vec<TypeDefinition<'_>> {
4694 let mut out = Vec::new();
4695 let mut at = start;
4696 while at < end {
4697 let declared = usize::from(bytes[at]);
4698 let Some(length) = declared.checked_sub(1) else {
4699 at += 1;
4700 continue;
4701 };
4702 let name_start = at + 1;
4703 let name_end = name_start.saturating_add(length);
4704 let Some(raw) = bytes.get(name_start..name_end) else {
4705 at += 1;
4706 continue;
4707 };
4708 let valid = raw.starts_with(b"UGS::")
4709 && raw.iter().all(|byte| (0x20..0x7f).contains(byte))
4710 && name_end < end;
4711 if valid {
4712 let name = std::str::from_utf8(raw)
4713 .expect("invariant: validated printable ASCII is valid UTF-8");
4714 out.push(TypeDefinition {
4715 offset: at,
4716 name,
4717 trailing_code: bytes[name_end],
4718 registry_suffix: &[],
4719 });
4720 at = name_end + 1;
4721 } else {
4722 at += 1;
4723 }
4724 }
4725 for index in 0..out.len().saturating_sub(1) {
4726 let suffix_start = out[index].offset + out[index].name.len() + 2;
4727 let suffix_end = out[index + 1].offset;
4728 out[index].registry_suffix = &bytes[suffix_start..suffix_end];
4729 }
4730 out
4731}
4732
4733fn field_definitions(bytes: &[u8], start: usize, end: usize) -> Vec<FieldDefinition<'_>> {
4734 let mut out = Vec::new();
4735 let mut search = start;
4736 let mut limit = start.saturating_add(256).min(end);
4737 while let Some((definition, at)) = (search..limit)
4738 .find_map(|at| field_definition_at(bytes, at, end).map(|definition| (definition, at)))
4739 {
4740 let next = at + definition.name.len() + 2;
4741 search = next;
4742 limit = search.saturating_add(256).min(end);
4743 out.push(definition);
4744 }
4745 bound_field_registry_suffixes(bytes, &mut out);
4746 out
4747}
4748
4749fn all_field_definitions(bytes: &[u8], start: usize, end: usize) -> Vec<FieldDefinition<'_>> {
4750 let mut out = Vec::new();
4751 let mut at = start;
4752 while at < end {
4753 if let Some(definition) = field_definition_at(bytes, at, end) {
4754 at += definition.name.len() + 2;
4755 out.push(definition);
4756 } else {
4757 at += 1;
4758 }
4759 }
4760 bound_field_registry_suffixes(bytes, &mut out);
4761 out
4762}
4763
4764fn bound_field_registry_suffixes<'a>(bytes: &'a [u8], definitions: &mut [FieldDefinition<'a>]) {
4765 for index in 0..definitions.len().saturating_sub(1) {
4766 let suffix_start = definitions[index].offset + definitions[index].name.len() + 2;
4767 let suffix_end = definitions[index + 1].offset;
4768 definitions[index].registry_suffix = &bytes[suffix_start..suffix_end];
4769 }
4770}
4771
4772fn field_definition_at(bytes: &[u8], at: usize, end: usize) -> Option<FieldDefinition<'_>> {
4773 let declared = usize::from(*bytes.get(at)?);
4774 let length = declared.checked_sub(1)?;
4775 let name_start = at.checked_add(1)?;
4776 let name_end = name_start.checked_add(length)?;
4777 (name_end < end).then_some(())?;
4778 let raw = bytes.get(name_start..name_end)?;
4779 (raw.starts_with(b"m_") && raw.iter().all(|byte| (0x20..0x7f).contains(byte))).then_some(())?;
4780 Some(FieldDefinition {
4781 offset: at,
4782 name: std::str::from_utf8(raw).ok()?,
4783 trailing_code: bytes[name_end],
4784 registry_suffix: &[],
4785 })
4786}
4787
4788fn numeric_expression_at(
4789 bytes: &[u8],
4790 base_offset: usize,
4791 object_id: Option<u32>,
4792) -> Option<NumericExpression<'_>> {
4793 const PREFIX: &[u8] = b"(Number [";
4794 let relative = bytes
4795 .windows(PREFIX.len())
4796 .position(|window| window == PREFIX)?;
4797 if relative < 3 || bytes.get(relative - 2) != Some(&0x04) {
4798 return None;
4799 }
4800 let declared = usize::from(*bytes.get(relative - 1)?);
4801 let text_len = declared.checked_sub(2)?;
4802 let text_end = relative.checked_add(text_len)?;
4803 (bytes.get(text_end) == Some(&0)).then_some(())?;
4804 let text = std::str::from_utf8(bytes.get(relative..text_end)?).ok()?;
4805 text.ends_with("; ").then_some(())?;
4806 let text = text.strip_prefix("(Number [")?;
4807 let (unit, rest) = text.split_once("]) ")?;
4808 let unit = match unit {
4809 "mm" => ExpressionUnit::Millimeter,
4810 "degrees" => ExpressionUnit::Degree,
4811 _ => return None,
4812 };
4813 let (name, value_tail) = rest.split_once(": ")?;
4814 if name.is_empty()
4815 || !name
4816 .bytes()
4817 .all(|byte| byte.is_ascii_alphanumeric() || byte == b'_')
4818 {
4819 return None;
4820 }
4821 let value_text = value_tail.strip_suffix("; ")?;
4822 let (parameter_index, qualifier) = parameter_name_parts(name)
4823 .map_or((None, None), |(index, qualifier)| (Some(index), qualifier));
4824 let value = evaluate_constant_expression(value_text);
4825 Some(NumericExpression {
4826 object_id,
4827 offset: base_offset + relative,
4828 name,
4829 parameter_index,
4830 qualifier,
4831 unit,
4832 expression: value_text,
4833 value,
4834 })
4835}
4836
4837pub(crate) fn evaluate_constant_expression(text: &str) -> Option<f64> {
4841 struct Parser<'a> {
4842 bytes: &'a [u8],
4843 at: usize,
4844 }
4845
4846 impl Parser<'_> {
4847 fn spaces(&mut self) {
4848 while self.bytes.get(self.at).is_some_and(u8::is_ascii_whitespace) {
4849 self.at += 1;
4850 }
4851 }
4852
4853 fn take(&mut self, byte: u8) -> bool {
4854 self.spaces();
4855 if self.bytes.get(self.at) == Some(&byte) {
4856 self.at += 1;
4857 true
4858 } else {
4859 false
4860 }
4861 }
4862
4863 fn sum(&mut self) -> Option<f64> {
4864 let mut value = self.product()?;
4865 loop {
4866 if self.take(b'+') {
4867 value += self.product()?;
4868 } else if self.take(b'-') {
4869 value -= self.product()?;
4870 } else {
4871 return value.is_finite().then_some(value);
4872 }
4873 }
4874 }
4875
4876 fn product(&mut self) -> Option<f64> {
4877 let mut value = self.unary()?;
4878 loop {
4879 if self.take(b'*') {
4880 value *= self.unary()?;
4881 } else if self.take(b'/') {
4882 value /= self.unary()?;
4883 } else {
4884 return value.is_finite().then_some(value);
4885 }
4886 }
4887 }
4888
4889 fn power(&mut self) -> Option<f64> {
4890 let value = self.primary()?;
4891 if self.take(b'^') {
4892 let result = value.powf(self.unary()?);
4893 result.is_finite().then_some(result)
4894 } else {
4895 Some(value)
4896 }
4897 }
4898
4899 fn unary(&mut self) -> Option<f64> {
4900 if self.take(b'+') {
4901 self.unary()
4902 } else if self.take(b'-') {
4903 Some(-self.unary()?)
4904 } else {
4905 self.power()
4906 }
4907 }
4908
4909 fn primary(&mut self) -> Option<f64> {
4910 if self.take(b'(') {
4911 let value = self.sum()?;
4912 self.take(b')').then_some(value)
4913 } else {
4914 self.number()
4915 }
4916 }
4917
4918 fn number(&mut self) -> Option<f64> {
4919 self.spaces();
4920 let start = self.at;
4921 while self
4922 .bytes
4923 .get(self.at)
4924 .is_some_and(|byte| byte.is_ascii_digit() || *byte == b'.')
4925 {
4926 self.at += 1;
4927 }
4928 if self
4929 .bytes
4930 .get(self.at)
4931 .is_some_and(|byte| matches!(byte, b'e' | b'E'))
4932 {
4933 self.at += 1;
4934 if self
4935 .bytes
4936 .get(self.at)
4937 .is_some_and(|byte| matches!(byte, b'+' | b'-'))
4938 {
4939 self.at += 1;
4940 }
4941 let exponent = self.at;
4942 while self.bytes.get(self.at).is_some_and(u8::is_ascii_digit) {
4943 self.at += 1;
4944 }
4945 (self.at > exponent).then_some(())?;
4946 }
4947 (self.at > start).then_some(())?;
4948 std::str::from_utf8(&self.bytes[start..self.at])
4949 .ok()?
4950 .parse()
4951 .ok()
4952 }
4953 }
4954
4955 let mut parser = Parser {
4956 bytes: text.as_bytes(),
4957 at: 0,
4958 };
4959 let value = parser.sum()?;
4960 parser.spaces();
4961 (parser.at == parser.bytes.len() && value.is_finite()).then_some(value)
4962}
4963
4964pub(crate) fn parameter_name_parts(name: &str) -> Option<(u32, Option<&str>)> {
4966 let tail = name.strip_prefix('p')?;
4967 let digit_count = tail.bytes().take_while(u8::is_ascii_digit).count();
4968 if digit_count == 0 {
4969 return None;
4970 }
4971 let index = tail[..digit_count].parse().ok()?;
4972 match &tail[digit_count..] {
4973 "" => Some((index, None)),
4974 suffix => {
4975 let qualifier = suffix.strip_prefix('_').filter(|qualifier| {
4976 !qualifier.is_empty()
4977 && qualifier
4978 .bytes()
4979 .all(|byte| byte.is_ascii_alphanumeric() || byte == b'_')
4980 });
4981 qualifier.map(|qualifier| (index, Some(qualifier)))
4982 }
4983 }
4984}