pdf_engine/api.rs
1//! The ideal top-level API facade for the PDFluent SDK.
2//!
3//! This module defines the intended public surface of the PDFluent library,
4//! following the "Zero-Config First Success", "Pit of Success", and "Progressive Disclosure"
5//! design principles.
6
7use std::path::Path;
8
9pub use crate::api_error::Error;
10
11/// Input source for a PDF document — accepts either a filesystem path or
12/// in-memory bytes.
13pub enum PdfSource<'a> {
14 /// Read the PDF from a filesystem path.
15 Path(&'a Path),
16 /// Read the PDF from an in-memory byte slice.
17 Bytes(&'a [u8]),
18}
19
20impl<'a> From<&'a str> for PdfSource<'a> {
21 fn from(s: &'a str) -> Self {
22 PdfSource::Path(Path::new(s))
23 }
24}
25
26impl<'a> From<&'a Path> for PdfSource<'a> {
27 fn from(p: &'a Path) -> Self {
28 PdfSource::Path(p)
29 }
30}
31
32impl<'a> From<&'a [u8]> for PdfSource<'a> {
33 fn from(b: &'a [u8]) -> Self {
34 PdfSource::Bytes(b)
35 }
36}
37
38/// Options for reading a PDF.
39#[derive(Default, Debug, Clone)]
40pub struct ReadOptions {
41 pub(crate) password: Option<String>,
42 pub(crate) repair: bool,
43}
44
45impl ReadOptions {
46 /// Construct default `ReadOptions` (no password, no repair).
47 pub fn new() -> Self {
48 Self::default()
49 }
50
51 /// Set a password to attempt when the PDF is encrypted (user or owner
52 /// password). Ignored on unencrypted documents.
53 pub fn password(&mut self, pw: impl Into<String>) -> &mut Self {
54 self.password = Some(pw.into());
55 self
56 }
57
58 /// Enable best-effort recovery of malformed PDFs (broken xref,
59 /// truncated streams). Slower but loads more inputs.
60 pub fn repair(&mut self, repair: bool) -> &mut Self {
61 self.repair = repair;
62 self
63 }
64}
65
66/// Options for saving a PDF.
67#[derive(Default, Debug, Clone)]
68pub struct SaveOptions {
69 pub(crate) format: Option<PdfFormat>,
70 pub(crate) linearize: bool,
71}
72
73impl SaveOptions {
74 /// Construct default `SaveOptions` (preserve input format, no
75 /// linearization).
76 pub fn new() -> Self {
77 Self::default()
78 }
79
80 /// Force the saver to emit a specific PDF or PDF/A version. When unset,
81 /// the input document's version is preserved.
82 pub fn format(&mut self, format: PdfFormat) -> &mut Self {
83 self.format = Some(format);
84 self
85 }
86
87 /// Linearize the output for "fast web view" — the saver reorders
88 /// objects so a viewer can render the first page before the full file
89 /// has downloaded.
90 pub fn linearize(&mut self, linearize: bool) -> &mut Self {
91 self.linearize = linearize;
92 self
93 }
94}
95
96/// PDF or PDF/A target version that the saver should emit. Used by
97/// [`SaveOptions::format`].
98#[derive(Debug, Clone, Copy, PartialEq, Eq)]
99pub enum PdfFormat {
100 /// PDF 1.4 — broadest reader compatibility, no AES-256.
101 Pdf1_4,
102 /// PDF 1.7 (ISO 32000-1) — modern baseline.
103 Pdf1_7,
104 /// PDF 2.0 (ISO 32000-2) — required for AES-256 (`V=5, R=6`).
105 Pdf2_0,
106 /// PDF/A-1b (ISO 19005-1, level B) — basic archival.
107 PdfA1b,
108 /// PDF/A-2b (ISO 19005-2, level B) — adds JPEG 2000, transparency.
109 PdfA2b,
110 /// PDF/A-3b (ISO 19005-3, level B) — adds arbitrary file attachments
111 /// (used for ZUGFeRD/Factur-X).
112 PdfA3b,
113}
114
115/// Options for [`Document::add_watermark`]. Defaults: opaque, unrotated.
116#[derive(Default, Debug, Clone)]
117pub struct WatermarkOptions {
118 /// Opacity, 0.0 (transparent) to 1.0 (opaque). Out-of-range values
119 /// clamp at 0.0/1.0.
120 pub opacity: f64,
121 /// Rotation in degrees around the page center. Positive =
122 /// counter-clockwise.
123 pub rotation: f64,
124}
125
126/// Output format selector for [`Document::to_images`]. PNG for line art /
127/// text, JPEG for photographic content.
128#[derive(Debug, Clone, Copy, PartialEq, Eq)]
129pub enum ImageFormat {
130 /// Lossless PNG — preserves text edges and line art.
131 Png,
132 /// Lossy JPEG — smaller output for photographic pages.
133 Jpeg,
134}
135
136/// A structured block of text from a PDF, with its bounding box on the
137/// page. Returned by [`Document::structured_text`].
138pub struct TextBlock {
139 /// Block text content in reading order.
140 pub text: String,
141 /// Bounding box `[llx, lly, urx, ury]` in PDF user-space points
142 /// (1/72 inch). Origin is the bottom-left of the page.
143 pub bbox: [f64; 4],
144}
145
146/// Document-level metadata read from the `/Info` dictionary or XMP. All
147/// fields are `None` if absent. Returned by [`Document::metadata`].
148pub struct Metadata {
149 /// `/Title`. `None` if not set.
150 pub title: Option<String>,
151 /// `/Author`. `None` if not set.
152 pub author: Option<String>,
153 /// `/CreationDate` as a PDF date string
154 /// (`D:YYYYMMDDHHmmSSOHH'mm'`). May be malformed in legacy
155 /// documents — parse defensively.
156 pub creation_date: Option<String>,
157}
158
159/// An interactive form field as seen by the form-fill API. One entry per
160/// terminal field; group fields are flattened. Returned by
161/// [`Document::form_fields`].
162pub struct FormField {
163 /// Fully-qualified field name (`parent.child` notation).
164 pub name: String,
165 /// Current field value as a string. For checkboxes this is the
166 /// "on"-state name (e.g. `"Yes"`, `"Off"`); for choice fields, the
167 /// selected option.
168 pub value: String,
169 /// Field-type discriminator: `"Tx"` (text), `"Btn"` (button),
170 /// `"Ch"` (choice), `"Sig"` (signature).
171 pub field_type: String,
172}
173
174/// A digital signature widget found in the document. Returned by
175/// [`Document::signatures`]; cryptographic verification is performed
176/// separately by [`Document::verify_signatures`].
177pub struct Signature {
178 /// Display name from the signature dictionary's `/Name` entry, or
179 /// from the certificate's subject if `/Name` is absent.
180 pub signer_name: String,
181 /// Signing time as a PDF date string. May be the signer's local
182 /// time (untrusted) or a TSA timestamp (trusted) depending on the
183 /// PAdES profile.
184 pub date: String,
185 /// `true` if the signature digest matches and the certificate chain
186 /// validates. For full validation reports, see
187 /// [`Document::verify_signatures`].
188 pub is_valid: bool,
189}
190
191/// The main entry point for a PDF Document.
192pub struct Document {
193 // Internal handle to actual implementation would go here
194}
195
196impl Document {
197 // === TEKST ===
198
199 /// Extracts plain text from all pages.
200 pub fn text(&self) -> String {
201 unimplemented!("facade")
202 }
203
204 /// Accesses a specific page for text extraction and other operations (1-based index).
205 pub fn page(&self, page_number: usize) -> Page {
206 let _ = page_number;
207 unimplemented!("facade")
208 }
209
210 /// Extracts structured text blocks with coordinates.
211 pub fn structured_text(&self) -> Vec<TextBlock> {
212 unimplemented!("facade")
213 }
214
215 // === METADATA ===
216
217 /// Returns the total number of pages in the document.
218 pub fn page_count(&self) -> usize {
219 unimplemented!("facade")
220 }
221
222 /// Returns the document's metadata.
223 pub fn metadata(&self) -> Metadata {
224 unimplemented!("facade")
225 }
226
227 // === OPSLAAN ===
228
229 /// Saves the document to a file.
230 pub fn save(&self, path: impl AsRef<Path>) -> Result<(), Error> {
231 let _ = path;
232 unimplemented!("facade")
233 }
234
235 /// Saves the document with specific options.
236 pub fn save_with<F>(&self, path: impl AsRef<Path>, build_opts: F) -> Result<(), Error>
237 where
238 F: FnOnce(&mut SaveOptions) -> &mut SaveOptions,
239 {
240 let _ = path;
241 let _ = build_opts;
242 unimplemented!("facade")
243 }
244
245 // === FORMULIEREN ===
246
247 /// Gets all form fields in the document.
248 pub fn form_fields(&self) -> Vec<FormField> {
249 unimplemented!("facade")
250 }
251
252 /// Fills form fields matching the provided name-value pairs.
253 pub fn fill_form(&self, fields: &[(&str, &str)]) -> Result<(), Error> {
254 let _ = fields;
255 unimplemented!("facade")
256 }
257
258 /// Flattens all forms, converting them to static content.
259 pub fn flatten_forms(&self) -> Result<(), Error> {
260 unimplemented!("facade")
261 }
262
263 // === HANDTEKENINGEN ===
264
265 /// Signs the document using the provided certificate and private key.
266 pub fn sign(&self, certificate: &[u8], private_key: &[u8]) -> Result<(), Error> {
267 let _ = certificate;
268 let _ = private_key;
269 unimplemented!("facade")
270 }
271
272 /// Retrieves all signatures from the document.
273 pub fn signatures(&self) -> Vec<Signature> {
274 unimplemented!("facade")
275 }
276
277 /// Verifies the cryptographic validity of all signatures.
278 pub fn verify_signatures(&self) -> Result<bool, Error> {
279 unimplemented!("facade")
280 }
281
282 // === REDACTIE ===
283
284 /// Redacts all occurrences of the specified text.
285 pub fn redact(&self, text: &str) -> Result<(), Error> {
286 let _ = text;
287 unimplemented!("facade")
288 }
289
290 /// Redacts a specific rectangular region on the specified page.
291 pub fn redact_region(&self, page: usize, rect: [f64; 4]) -> Result<(), Error> {
292 let _ = page;
293 let _ = rect;
294 unimplemented!("facade")
295 }
296
297 // === CONVERSIE ===
298
299 /// Converts the document to a DOCX file.
300 pub fn to_docx(&self, path: impl AsRef<Path>) -> Result<(), Error> {
301 let _ = path;
302 unimplemented!("facade")
303 }
304
305 /// Renders the document's pages to images based on a filename pattern.
306 pub fn to_images(&self, pattern: &str, format: ImageFormat) -> Result<(), Error> {
307 let _ = pattern;
308 let _ = format;
309 unimplemented!("facade")
310 }
311
312 /// Checks if the document is PDF/A compliant.
313 pub fn is_pdfa_compliant(&self) -> Result<bool, Error> {
314 unimplemented!("facade")
315 }
316
317 // === MANIPULATIE ===
318
319 /// Merges another document into this one.
320 pub fn merge(&self, other_doc: &Document) -> Result<(), Error> {
321 let _ = other_doc;
322 unimplemented!("facade")
323 }
324
325 /// Splits the document into individual 1-page documents.
326 pub fn split_pages(&self) -> Result<Vec<Document>, Error> {
327 unimplemented!("facade")
328 }
329
330 /// Rotates a specific page by the given angle (in degrees).
331 pub fn rotate_page(&self, page: usize, angle: i32) -> Result<(), Error> {
332 let _ = page;
333 let _ = angle;
334 unimplemented!("facade")
335 }
336
337 /// Adds a watermark to all pages of the document.
338 pub fn add_watermark(&self, text: &str, options: WatermarkOptions) -> Result<(), Error> {
339 let _ = text;
340 let _ = options;
341 unimplemented!("facade")
342 }
343}
344
345/// Represents a single page within a Document.
346pub struct Page {
347 // Internal handle to the specific page
348}
349
350impl Page {
351 /// Extracts plain text from this page only.
352 pub fn text(&self) -> String {
353 unimplemented!("facade")
354 }
355}
356
357// === LEZEN (Top-level functions) ===
358
359/// Reads a PDF document from a file path or bytes, using default options.
360pub fn read<'a, S: Into<PdfSource<'a>>>(input: S) -> Result<Document, Error> {
361 let _ = input;
362 unimplemented!("facade")
363}
364
365/// Reads a PDF document with custom options (e.g., providing a password).
366pub fn read_with<'a, S, F>(input: S, build_opts: F) -> Result<Document, Error>
367where
368 S: Into<PdfSource<'a>>,
369 F: FnOnce(&mut ReadOptions) -> &mut ReadOptions,
370{
371 let _ = input;
372 let _ = build_opts;
373 unimplemented!("facade")
374}