rasgapdf / docs /ARCHITECTURE.md
martinsmessias's picture
chore: update release packages, bindings and publish script
1606e9e verified
|
Raw History Blame Contribute Delete
3.46 kB

🏛️ RasgaPDF Architecture & Technical Design

RasgaPDF was designed with a single uncompromising mission: deliver 2D physical spatial PDF layout analysis at native hardware speed with sub-millisecond latencies.


1. High-Level Architecture Diagram

flowchart TD
    INPUT["Input PDF File / Buffer"] --> CORE["RasgaPDF Core (Rust)"]
    
    subgraph CORE["RasgaPDF High-Performance Engine"]
        MUPDF["MuPDF C-Binding"] --> PARALLEL["Rayon Parallel Pipeline"]
        PARALLEL --> PAGE_WORKER["Page Geometric Deconstruction"]
        PAGE_WORKER --> SPAN_EXTRACT["Physical Spans & Bounding Boxes"]
        PAGE_WORKER --> GRAPHICS["Embedded Images & Vector Paths (opt-in)"]
        SPAN_EXTRACT --> BUCKET_SORT["Y-Bucket & X-Order Spatial Sort"]
        BUCKET_SORT --> TABLE_DETECTOR["2D Column Projection Table Detector"]
        TABLE_DETECTOR --> SERIALIZER["Zero-Copy Serde JSON Serializer"]
        GRAPHICS --> SERIALIZER
    end
    
    SERIALIZER --> FFI["C-ABI FFI Layer (librasgapdf.so / .dll / .dylib)"]
    
    subgraph BINDINGS["Multi-Language Polyglot Bindings"]
        FFI --> PY["Python (ctypes / PyO3)"]
        FFI --> NODE["Node.js (koffi / CLI)"]
        FFI --> GO["Go (cgo)"]
        FFI --> CS["C# / .NET 8 (P/Invoke)"]
        CORE --> CLI["Standalone CLI Binary"]
    end

2. Core Principles

A. Zero Guesswork, Exact Geometry

Standard PDF parsers attempt to guess Markdown headers (# Header), indentation, or bullet points using fragile heuristics. When applied to multi-column newspapers, medical records, or invoices, these heuristics fail catastrophically.

RasgaPDF returns exact 2D physical bounds:

  • x0, y0, x1, y1 (top-left to bottom-right).
  • Real typography: Font name, font size, character count.
  • Structured table cells with row and column indices.

B. Embarrassingly Parallel Parsing (rayon)

PDF pages are completely independent data structures. RasgaPDF spawns worker threads matching your CPU core count using rayon::into_par_iter(). A 100-page document processes simultaneously across all available CPU threads with linear scalability.

C. Unified C-ABI Polyglot Architecture

Rather than reimplementing geometric algorithms in 5 different languages, RasgaPDF maintains a single source of truth in Rust (C99 ABI). The resulting shared library exports clean, thread-safe functions that can be imported by Python, JavaScript, Go, C#, Java, or C++ with zero friction.

D. Graphics Without Pixel Bloat (opt-in)

Embedded images and vector paths are extracted in the same per-page worker, but only when requested (extract_images / extract_drawings). Image bytes are never inlined in the JSON: the tree carries metadata (dimensions, colour space, filter, byte length, SHA-256, placement bbox) and the original encoded stream is written to disk (--extract-images DIR) or returned as Vec<u8> by the Rust API. This keeps documents with large scans as light as text-only ones.

E. Local DTOs Instead of mupdf::page::StextPage

MuPDF's structured-text JSON emits image blocks ({"type":"image","bbox":{…}}) without the lines field, which the upstream StextPage type requires. RasgaPDF deserializes into its own minimal DTOs (RawStextPage/RawBlock/RawLine/RawFont) where every field is optional. This tolerates image and structure blocks and prevents a single unusual block from silently emptying an entire page.