Feat: add LoadedPdf handle and PdfDocument handle (wasm) for repeated page processing
Currently the whole PDF doc is re-processed for extracting a new page range. This PR adds an API to let the API caller hold a loaded PDF doc so that later extraction does not require re-processing. I did a benchmark with NASA/TM-2014-217388 (release build, NASA PDF, one page per call, markdown asserted identical):
| Pages | One-shot | LoadedPdf |
|---|---|---|
| 20 | 752 ms (37.6 ms/page) | 52 ms (2.4 ms/page) |
| 197 | 7.14 s (36.2 ms/page) | 249 ms (1.2 ms/page) |
LoadedPdf (Rust) and PdfDocument (WebAssembly) open a PDF once and process it any number of times: LoadedPdf::process_pages(options) and new PdfDocument(data, password?).processPages(options) give the result process_pdf_mem_with_options and processPdf give for the same options, without parsing the file again. Detection, the font CMaps and the structure tree are computed by the first call that needs them and kept.
This PR is implemented with the assistance from AI
Summary by cubic
Adds LoadedPdf (Rust) and PdfDocument (WebAssembly) handles that parse a PDF once and process any pages of it any number of times. process_pdf_mem_with_options and processPdf re-parse the whole file on every call even for one page; opening once drops per-page processing from ~36 ms to ~1.2 ms on a 197-page benchmark PDF.
Notes
LoadedPdf::process_pages(options)andnew PdfDocument(data, password?).processPages(options)return the same result as the one-shot functions for the same options.- Detection is cached for the most recent
DetectionConfigonly; the font CMaps and the structure tree are computed by the first call that needs them and kept. process_pagesignoresoptions.passwordsince the document is already open;page_count, document type, and the OCR page list still describe the whole document.- The one-shot functions now delegate to the same pipeline, so their results are unchanged.