Skip to main content

Pipeline

Struct Pipeline 

Source
pub struct Pipeline { /* private fields */ }
Expand description

A reusable PDF pipeline. The primary worker runs its models on every core, so a single-page / small / image / METS input is converted at full intra-op speed with no pool to load. A document with enough pages instead fans out across a pool of narrower workers processed concurrently. Both load lazily and are cached for reuse, so a one-shot conversion only pays for what it uses.

Implementations§

Source§

impl Pipeline

Source

pub fn new() -> Result<Self, PdfError>

Construct the pipeline. Models load lazily on first use (full-intra primary for serial inputs, the helper pool for multi-page PDFs), so nothing is loaded that a given document doesn’t need.

Examples found in repository?
examples/snapshot.rs (line 55)
47fn main() {
48    let mut args = std::env::args().skip(1);
49    let root = PathBuf::from(args.next().expect("usage: snapshot <root> <outdir>"));
50    let outdir = PathBuf::from(args.next().expect("usage: snapshot <root> <outdir>"));
51
52    let mut pdfs = Vec::new();
53    find_pdfs(&root, &mut pdfs);
54
55    let mut pipeline = Pipeline::new().expect("load pipeline");
56    let (mut ok, mut err) = (0u32, 0u32);
57    for pdf in &pdfs {
58        let rel = pdf.strip_prefix(&root).unwrap_or(pdf);
59        let name = pdf.file_name().unwrap().to_string_lossy().to_string();
60        let md = match std::fs::read(pdf)
61            .map_err(|e| format!("read: {e}"))
62            .and_then(|bytes| {
63                let ext = pdf.extension().and_then(|e| e.to_str()).unwrap_or("");
64                let result = if ext == "gz" {
65                    docling_pdf::convert_mets_gbs(&bytes, &name)
66                } else if IMAGE_EXTS.contains(&ext) {
67                    pipeline.convert_image(&bytes, &name)
68                } else {
69                    pipeline.convert(&bytes, None, &name)
70                };
71                result
72                    .map(|d| d.export_to_markdown())
73                    .map_err(|e| e.to_string())
74            }) {
75            Ok(md) => {
76                ok += 1;
77                md
78            }
79            Err(e) => {
80                err += 1;
81                eprintln!("ERR {}: {e}", rel.display());
82                format!("ERROR: {e}\n")
83            }
84        };
85        // Groundtruth naming keeps the source extension: `<file>.<ext>.md`.
86        let mut dest = outdir.join(rel).into_os_string();
87        dest.push(".md");
88        let dest = PathBuf::from(dest);
89        std::fs::create_dir_all(dest.parent().unwrap()).expect("mkdir");
90        std::fs::write(&dest, md).expect("write snapshot");
91    }
92    eprintln!("snapshots: {} ok, {} error, {} total", ok, err, pdfs.len());
93}
Source

pub fn enrichments(self, opts: EnrichmentOptions) -> Self

Enable the opt-in enrichment passes (docling’s do_picture_classification / do_code_enrichment / do_formula_enrichment). Each enabled pass lazily loads its model on the first matching region; a missing model warns once and is skipped. Set before the first conversion (no effect on already-loaded workers).

Source

pub fn no_table_former(self, disable: bool) -> Self

Skip loading and running the TableFormer table-structure model. Table regions still get emitted, but reconstructed geometrically from cell positions instead of via the ONNX model’s predicted structure — faster (no model load, no per-table inference) at the cost of table fidelity. No effect if a worker is already loaded; set this before the first conversion.

Source

pub fn no_ocr(self, disable: bool) -> Self

Skip layout detection, OCR, and TableFormer entirely — no model load, no inference of any kind. The PDF’s embedded text cells are grouped by line and emitted as plain paragraphs in reading order: no headings, lists, tables, code blocks, or pictures, since that structure comes from the layout model. The fastest possible PDF path, but pages with no embedded text layer (scanned/image-only PDFs) yield no text at all — convert those without this flag. Implies no_table_former. No effect if a worker is already loaded; set this before the first conversion.

Source

pub fn warm_up(&mut self) -> Result<(), PdfError>

Eagerly load the models (the full-intra serial worker: layout + OCR, and the shared TableFormer unless disabled) so the first conversion doesn’t pay the load cost. Idempotent; respects no_ocr / no_table_former (with no_ocr there is nothing to load). The docling.rs analogue of docling’s DocumentConverter.initialize_pipeline.

Source

pub fn convert( &mut self, bytes: &[u8], password: Option<&str>, name: &str, ) -> Result<DoclingDocument, PdfError>

Convert a PDF (bytes) to a DoclingDocument. A document with fewer than parallel_min pages (or a pool size of 1) streams through the full-intra primary; a larger one renders on this thread (pdfium is not thread-safe) and fans the pages out across the worker pool, reassembled in page order so the output is byte-identical to the serial path.

Examples found in repository?
examples/snapshot.rs (line 69)
47fn main() {
48    let mut args = std::env::args().skip(1);
49    let root = PathBuf::from(args.next().expect("usage: snapshot <root> <outdir>"));
50    let outdir = PathBuf::from(args.next().expect("usage: snapshot <root> <outdir>"));
51
52    let mut pdfs = Vec::new();
53    find_pdfs(&root, &mut pdfs);
54
55    let mut pipeline = Pipeline::new().expect("load pipeline");
56    let (mut ok, mut err) = (0u32, 0u32);
57    for pdf in &pdfs {
58        let rel = pdf.strip_prefix(&root).unwrap_or(pdf);
59        let name = pdf.file_name().unwrap().to_string_lossy().to_string();
60        let md = match std::fs::read(pdf)
61            .map_err(|e| format!("read: {e}"))
62            .and_then(|bytes| {
63                let ext = pdf.extension().and_then(|e| e.to_str()).unwrap_or("");
64                let result = if ext == "gz" {
65                    docling_pdf::convert_mets_gbs(&bytes, &name)
66                } else if IMAGE_EXTS.contains(&ext) {
67                    pipeline.convert_image(&bytes, &name)
68                } else {
69                    pipeline.convert(&bytes, None, &name)
70                };
71                result
72                    .map(|d| d.export_to_markdown())
73                    .map_err(|e| e.to_string())
74            }) {
75            Ok(md) => {
76                ok += 1;
77                md
78            }
79            Err(e) => {
80                err += 1;
81                eprintln!("ERR {}: {e}", rel.display());
82                format!("ERROR: {e}\n")
83            }
84        };
85        // Groundtruth naming keeps the source extension: `<file>.<ext>.md`.
86        let mut dest = outdir.join(rel).into_os_string();
87        dest.push(".md");
88        let dest = PathBuf::from(dest);
89        std::fs::create_dir_all(dest.parent().unwrap()).expect("mkdir");
90        std::fs::write(&dest, md).expect("write snapshot");
91    }
92    eprintln!("snapshots: {} ok, {} error, {} total", ok, err, pdfs.len());
93}
Source

pub fn convert_streaming<F>( &mut self, bytes: &[u8], password: Option<&str>, name: &str, emit: F, ) -> Result<(), PdfError>
where F: FnMut(Vec<Node>, Vec<(String, String)>) -> Result<(), PdfError>,

Convert a PDF in streaming mode: emit is called with each finalized, in-document-order batch of nodes (and that span’s recovered links) as pages complete, so a caller can serialize Markdown page by page instead of waiting for the whole document. The batches are exactly the buffered convert’s nodes, split at safe block boundaries by [assemble::StreamAssembler] — the parallel path reorders pages back into document order before emitting, so the output is identical regardless of worker scheduling.

emit runs on the calling thread (never a worker), so it needn’t be Send and its backpressure throttles the whole pipeline. Returning Err from emit aborts the conversion with that error.

Source

pub fn convert_image( &mut self, bytes: &[u8], name: &str, ) -> Result<DoclingDocument, PdfError>

Convert a standalone image (PNG/JPEG/TIFF/WebP/…) as a single page — docling routes images through the same layout+OCR pipeline as a PDF page.

Examples found in repository?
examples/snapshot.rs (line 67)
47fn main() {
48    let mut args = std::env::args().skip(1);
49    let root = PathBuf::from(args.next().expect("usage: snapshot <root> <outdir>"));
50    let outdir = PathBuf::from(args.next().expect("usage: snapshot <root> <outdir>"));
51
52    let mut pdfs = Vec::new();
53    find_pdfs(&root, &mut pdfs);
54
55    let mut pipeline = Pipeline::new().expect("load pipeline");
56    let (mut ok, mut err) = (0u32, 0u32);
57    for pdf in &pdfs {
58        let rel = pdf.strip_prefix(&root).unwrap_or(pdf);
59        let name = pdf.file_name().unwrap().to_string_lossy().to_string();
60        let md = match std::fs::read(pdf)
61            .map_err(|e| format!("read: {e}"))
62            .and_then(|bytes| {
63                let ext = pdf.extension().and_then(|e| e.to_str()).unwrap_or("");
64                let result = if ext == "gz" {
65                    docling_pdf::convert_mets_gbs(&bytes, &name)
66                } else if IMAGE_EXTS.contains(&ext) {
67                    pipeline.convert_image(&bytes, &name)
68                } else {
69                    pipeline.convert(&bytes, None, &name)
70                };
71                result
72                    .map(|d| d.export_to_markdown())
73                    .map_err(|e| e.to_string())
74            }) {
75            Ok(md) => {
76                ok += 1;
77                md
78            }
79            Err(e) => {
80                err += 1;
81                eprintln!("ERR {}: {e}", rel.display());
82                format!("ERROR: {e}\n")
83            }
84        };
85        // Groundtruth naming keeps the source extension: `<file>.<ext>.md`.
86        let mut dest = outdir.join(rel).into_os_string();
87        dest.push(".md");
88        let dest = PathBuf::from(dest);
89        std::fs::create_dir_all(dest.parent().unwrap()).expect("mkdir");
90        std::fs::write(&dest, md).expect("write snapshot");
91    }
92    eprintln!("snapshots: {} ok, {} error, {} total", ok, err, pdfs.len());
93}

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V