Commit Graph
7 Commits
Author SHA1 Message Date
KenM76andClaude Opus 5.5 cb317560fe M12: PRC reader: answer review (#1297)
- Schema programs draw on one step allowance per reading pass:
  MAX_SCHEMA_STEPS (2^22) moves into the BitReader's budget next to the
  decoded-element allowance, and the tree walk carries both from reader
  to reader. A per-call ceiling let a cheap entity repeated many times
  run ~2^22 steps each.
- The vertex-colour pre-check charges the minimum encoding (one full
  colour, then one reuse bit each), so a run of reused colours may end a
  section.
- placements() reports unreadable globals when an entity reference, not
  only an item, names a reference coordinate system.
- chunks_exact -> as_chunks for clippy 1.99 (chunks_exact_to_as_chunks).

Tests: programs_on_one_stream_share_the_step_allowance,
one_step_allowance_covers_the_whole_walk,
reused_vertex_colours_may_be_the_last_data,
unreadable_globals_are_an_error_when_a_reference_names_a_coordinate_system;
each fails with its fix reverted.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SqmHYx8FiWM5PcsoiErgp9
2026-11-02 14:38:13 -05:00
KenM76andClaude Opus 5.5 a7cc7586d1 M12: PRC reader: cap decoded array elements per reading pass (#1297)
The inflation cap bounds bytes, but one bit can decode to a 4-8 byte
element, so a 512 MiB section could ask for about 16 GiB. Every array
count is now charged against MAX_DECODED_ELEMENTS (2^24), shared by
all readers of one tree walk; over the allowance is TooManyElements.
Huffman pre-sizing is capped at 1024.

decoded_elements_are_charged_against_one_allowance fails with the
charge in BitReader::take_elements removed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SqmHYx8FiWM5PcsoiErgp9
2026-11-02 13:27:05 -05:00
KenM76andClaude Opus 5.5 c566ca6144 M12: PRC reader: tree markups and views read past (#1297)
CAD 3D files carrying PMI failed model_tree() and placements() with
"tree markups (PMI) is not supported": the tree section has no length
prefix, so MarkupData and views had to be parsed to be skipped.

Now read past, not modelled (new tree/markup.rs):
- MarkupData [WD 7.3.10.4]: markup linked items (204), leaders (503),
  markups (502), annotation items/sets/references (504-506); sets
  nest under the MAX_DEPTH ceiling.
- Views (501) [WD 7.7.3], with their annotation plane (SURF_Plane 86),
  optional scene parameters, and from 8137 their flags, linked items
  and filters.
- Scene lights (731-734) and clipping planes, so
  SceneDisplayParameters no longer refuses them.
ReferenceData and ReferenceOnPRCBase are shared readers now, and skip
their schema-added fields.

Field orders the working draft leaves open follow prc-rs's format
description (MIT); each such reader carries a `prc-rs:` marker.

Tests: one synthetic test per entity kind (each reads to a sentinel
and every truncation errors), nesting ceiling, wrong annotation type,
and a tree with markups and views on a part and an occurrence that
still places its mesh. Each shown failing with its reader reverted.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SqmHYx8FiWM5PcsoiErgp9
2026-11-02 12:26:44 -05:00
KenM76andClaude Opus 5.5 c571b13469 M12: PRC reader: product tree and styles (#1297)
Walk the PRC product tree into placed, coloured tessellations.

- PrcFile::placements / placements_with(StyleAlpha, EntityOverrides):
  every drawable tessellation reached from the model file's roots, placed
  by its occurrence path's locations and then the representation item's
  local coordinate systems (a 4x4 Matrix) [WD 7.3.10.1, 7.6.3.2].
- Colours: styles and materials from the file structure globals, the
  father/son inheritance bits [WD 7.2.4.2], style transparency combined
  with material alpha by StyleAlpha, per-face styles and topology
  references via Placement::triangle_colours. A prototype's part is
  coloured by its own structure's styles. A colour index counts the colour
  array's doubles (pdf-issues #816).
- Occurrences' entity references: colour, hide or relocate the entity
  they name, in the occurrence's subtree, everywhere, or not at all.
- PrcFile::model_tree: the assembly tree as a model-tree panel lists it,
  with name sources, visibility and each node's placement range.
- TriangleMesh::transformed applies a Matrix: positions, cofactor-mapped
  normals, winding flipped under a mirror.

Never panics: occurrence and prototype cycles are Malformed; depth 64,
2^20 visits, MAX_PLACEMENTS and a face-override ceiling bound the walk;
counts are checked against the remaining data before allocating.
Markups, views, scene lights and clipping planes are Unsupported;
textures are read past.

Field orders the working draft leaves open follow prc-rs (MIT); each is
marked `// prc-rs:`, as are the step-1 container, Double and schema
choices that did.

Adapted from pdfcer (MIT, same author), crates/pdfcer-3d/src/tree and
vec3.rs at 0c9742b5936232af89cd707138ef149dc1f4a660.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SqmHYx8FiWM5PcsoiErgp9
2026-11-02 12:26:44 -05:00
KenM76andClaude Opus 5.5 7f30266790 M12: PRC reader: tessellation and arrays (#1297)
Read the tessellation section of a PRC file structure:
FileStructure::tessellations() returns each entity as a Tessellation.

- TESS_3D becomes a TriangleMesh: positions, triangles from the
  triangle/fan/strip blocks (one-normal and textured variants included),
  one triangle range per face, stored normals and texture coordinates
  with per-corner indices, and per-triangle line-attribute styles.
- TESS_3D_Wire becomes polylines (closing and continuous flags); vertex
  colours are read past, sized by points (closing point included).
- TESS_Markup is read past.
- TESS_3D_Compressed is read field by field to its end so the entities
  after it decode; its triangles are not rebuilt (later step).
- The compressed Character/Short/Integer/Indice arrays and the Huffman
  container they use (WD 11.6-11.9, 12.2) live in arrays.rs; the base
  fields every entity shares (attributes, name, user data) in entity.rs.

Never-panic hardening beyond the source this is adapted from:
- Huffman symbol width must be 1..=16; the leaf table and element count
  are bounded by the payload before anything is allocated.
- A face may carry at most 8 texture-coordinate sets (an unbounded
  count allocated per set and padded per triangle).
- Every count is checked against the remaining bits; indice sums and
  deltas use checked arithmetic.

A few reading choices (Huffman bit order and code-length width, indice
running sums, 64-bit attribute order, three version gates, the
is_segment_color bit, the compressed field order) follow prc-rs (MIT);
each is marked `// prc-rs:` in the source.

Tests are synthetic, written with the crate's test bit writer. Each
fix was reverted and its test seen failing (17 reversions).

Adapted from pdfcer (MIT, same author), pdfcer-3d at
0c9742b5936232af89cd707138ef149dc1f4a660.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SqmHYx8FiWM5PcsoiErgp9
2026-11-02 12:26:43 -05:00
KenM76andClaude Opus 5.5 ab552430a7 M12: PRC reader: the Double code table from prc-rs (MIT) (#1297)
Every PRC Double decodes through a fixed 2077-row prefix-code table
(working draft 11.17.2). The rows come from prc-rs src/double.rs at
287b671bb5b31b05efb5ec1b98f7c359b9e4dd7d under its MIT licence, whose
notice stays in the file header; ATTRIBUTION.toml records it.

The table is a complete prefix code, so the empty-table stub test is
replaced by a truncation test. The exponent lookup masks the 11 exponent
bits, because the last exponent row's upper word is 0x7ff80000.

Revert proof: with the table emptied, eight Double tests fail.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SqmHYx8FiWM5PcsoiErgp9
2026-11-02 12:26:43 -05:00
KenM76andClaude Opus 5.5 83b230ae73 M12: PRC reader crate: container, bit primitives, schema (#1297)
New standalone L0 crate pdfcraft-prc: the PRC container walk (file
header, file-structure descriptions, per-section zlib inflation under a
512 MiB ceiling), the bit-level primitives of the compressed sections,
and the schema interpreter a newer producer uses to describe fields it
added (step and nesting ceilings).

The Double prefix-code table is not in this commit: Double reads
return UnknownDoubleCode, and the tests that need the table are
ignored with that reason.

Adapted from pdfcer (MIT, same author), crates/pdfcer-3d at
0c9742b5936232af89cd707138ef149dc1f4a660.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SqmHYx8FiWM5PcsoiErgp9
2026-11-02 12:26:43 -05:00