Implements merge_hybrid() and is_hybrid_trailer() for hybrid PDF files. Hybrid files have both a traditional xref table at startxref and a supplementary xref stream pointed to by /XRefStm in the trailer. Per PDF spec, the traditional table is authoritative for objects it covers; the stream's type-2 entries fill gaps not covered by the traditional table. Key behaviors: - Traditional entries override stream entries for same object numbers - Stream-only type-2 entries are added as gap fill - Free/InUse conflicts emit STRUCT_HYBRID_CONFLICT diagnostic - Merged trailer has /XRefStm key removed - Result XrefSection has is_hybrid: true set Acceptance criteria: - Critical test: traditional entries override stream entries (PASS) - Gap fill: stream-only type-2 entries added (PASS) - Free/InUse conflict: diagnostic emitted (PASS) - Non-hybrid trailer: is_hybrid_trailer returns false (PASS) - proptest: no panics with random combinations (PASS) - INV-8 maintained: no panics in library code (PASS) Co-Authored-By: Claude Code <noreply@anthropic.com>
3.4 KiB
3.4 KiB
pdftract-5og4: Hybrid Xref Handler Implementation
Summary
Implemented the hybrid xref handler that merges traditional xref tables with xref streams for hybrid PDF files. The traditional table is authoritative for objects it covers; the stream's type-2 entries fill gaps not covered by the traditional table.
Changes Made
1. Added StructHybridConflict diagnostic code
- File:
crates/pdftract-core/src/parser/xref.rs - Added new variant to
XrefDiagCodeenum for hybrid conflict diagnostics
2. Fixed merge_hybrid function
- Fixed borrow checker error: was iterating by ownership then trying to borrow
- Changed to iterate by reference:
for (obj_nr, entry) in &traditional.entries - Updated to use new
XrefDiagCode::StructHybridConflictdiagnostic code - Removed unused
use crate::diagnostics::DiagCode;import
3. Updated test
- File:
crates/pdftract-core/src/parser/xref.rs - Updated
test_merge_hybrid_free_inuse_conflictto check forXrefDiagCode::StructHybridConflict - Removed unused
use crate::diagnostics::DiagCode;import
4. Exported public API
- File:
crates/pdftract-core/src/parser/mod.rs - Added
merge_hybridandis_hybrid_trailerto public re-exports
Acceptance Criteria Status
| Criterion | Status | Notes |
|---|---|---|
| Critical test passes: traditional entries override stream entries | PASS | test_merge_hybrid_traditional_priority |
| Hybrid fixture with stream-only type-2 entries: gap fill works | PASS | test_merge_hybrid_gap_fill |
| Free/InUse conflict test: STRUCT_HYBRID_CONFLICT diagnostic emitted | PASS | test_merge_hybrid_free_inuse_conflict |
| Non-hybrid trailer (no /XRefStm): merge not invoked | PASS | is_hybrid_trailer returns false |
| proptest: random combinations never panic | PASS | test_merge_hybrid_proptest_simple |
| INV-8 maintained | PASS | All tests pass, no regressions |
Test Results
All 9 hybrid xref tests pass:
test_merge_hybrid_traditional_priority- traditional entries override stream entriestest_merge_hybrid_free_inuse_conflict- Free/InUse conflict emits diagnostictest_merge_hybrid_gap_fill- stream-only type-2 entries fill gapstest_merge_hybrid_trailer_xrefstm_removed- /XRefStm key removed from merged trailertest_is_hybrid_trailer_detection- hybrid trailer detection workstest_merge_hybrid_empty_sections- edge case: empty sectionstest_merge_hybrid_stream_only- edge case: traditional empty, stream has entriestest_merge_hybrid_traditional_only- edge case: stream empty, traditional has entriestest_merge_hybrid_proptest_simple- proptest verifies no panics
Implementation Notes
The merge_hybrid function implements the correct priority semantics per PDF spec:
- Start with all traditional entries
- For each stream entry: if the same ObjRef is NOT in the traditional map, insert it
- If an ObjRef IS in the traditional map (even as type-1 Free), traditional wins
- Emit
STRUCT_HYBRID_CONFLICTdiagnostic when traditional Free conflicts with stream InUse - The merged trailer is the traditional one with
/XRefStmkey removed - The result has
is_hybrid: trueset
Files Modified
crates/pdftract-core/src/parser/xref.rs- Added diagnostic code, fixed merge function, updated testscrates/pdftract-core/src/parser/mod.rs- Exported public API functions
Git Commits
fix(pdftract-5og4): add StructHybridConflict diagnostic code and fix merge_hybrid borrow error