firecrawl_pdfium/lib.rs
1//! Safe, self-contained Rust bindings for [PDFium], Google's PDF engine:
2//! open documents from memory, inspect pages, render to **owned** pixel
3//! buffers, map coordinates between rendered pixels and PDF page space,
4//! extract positioned text, and draw form fields — safely usable from
5//! concurrent code.
6//!
7//! [PDFium]: https://pdfium.googlesource.com/pdfium/
8//!
9//! # Quickstart
10//!
11//! PDFium is loaded **at runtime** (no build-time linking): fetch a binary
12//! once with `cargo xtask fetch-pdfium` (repo checkouts), ship one next to
13//! your executable, or point `PDFIUM_LIB_PATH` at one. Then:
14//!
15//! ```no_run
16//! use firecrawl_pdfium::{Pdfium, RenderConfig};
17//!
18//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
19//! // Discovery chain: $PDFIUM_LIB_PATH → exe dir → ./target/pdfium → system.
20//! let pdfium = Pdfium::load()?;
21//!
22//! let bytes = std::fs::read("document.pdf")?;
23//! let doc = pdfium.load_document(bytes, None)?; // None = no password
24//! println!("{} pages", doc.page_count());
25//!
26//! let page = doc.page(0)?;
27//! let rendered = page.render(&RenderConfig::new().dpi(144.0))?;
28//! println!(
29//! "{}x{} pixels, {} bytes/row, {:?}",
30//! rendered.width(),
31//! rendered.height(),
32//! rendered.stride(),
33//! rendered.format(),
34//! );
35//!
36//! // Map a pixel back into PDF page space (points, origin bottom-left):
37//! let pt = rendered.transform().pixel_to_page((10.0, 10.0).into());
38//! println!("pixel (10,10) is at ({:.2}, {:.2})pt", pt.x, pt.y);
39//! # Ok(())
40//! # }
41//! ```
42//!
43//! # Errors on hostile input
44//!
45//! Encrypted documents surface as [`Error::PasswordRequired`] /
46//! [`Error::IncorrectPassword`] / [`Error::UnsupportedSecurity`]; garbage
47//! and truncated files as [`Error::InvalidPdf`]; oversized render requests
48//! as [`Error::RenderTooLarge`] (bounded by
49//! [`RenderConfig::max_output_bytes`]).
50//!
51//! # Concurrency model
52//!
53//! PDFium itself is single-threaded. Every call is serialized through one
54//! process-wide mutex, making all handle types `Send + Sync` — safe from
55//! any thread, but not parallel. See [`Pdfium`] for details and
56//! `docs/DESIGN.md` for the soundness argument. For parallel throughput,
57//! shard across processes.
58//!
59//! # Raw FFI escape hatch
60//!
61//! The [`sys`] module exposes the loaded function table for calls this
62//! crate does not wrap yet; combine with [`Pdfium::ffi_lock`] to stay
63//! within the serialization contract.
64
65#![deny(unsafe_op_in_unsafe_fn)]
66#![warn(missing_docs)]
67#![cfg_attr(docsrs, feature(doc_cfg))]
68
69mod coords;
70mod document;
71mod error;
72mod forms;
73mod library;
74mod page;
75mod render;
76mod text;
77
78pub mod sys;
79
80pub use coords::{PagePoint, PageRect, PageTransform, PixelPoint, PixelRect};
81pub use document::{MetadataTag, PdfDocument, Permissions};
82pub use error::{Error, LoadError, Result};
83pub use forms::FormType;
84pub use library::{platform_library_name, platform_slug, Pdfium, PDFIUM_LIB_PATH_ENV};
85pub use page::{PageSize, PdfPage, Rotation};
86pub use render::{Color, PixelFormat, RenderConfig, RenderedPage};
87pub use text::{PageChar, PageText, DEFAULT_MAX_TEXT_CHARS};
88
89impl From<(f64, f64)> for PixelPoint {
90 fn from((x, y): (f64, f64)) -> Self {
91 PixelPoint::new(x, y)
92 }
93}
94
95impl From<(f64, f64)> for PagePoint {
96 fn from((x, y): (f64, f64)) -> Self {
97 PagePoint::new(x, y)
98 }
99}