Skip to main content

otf_pdf/
lib.rs

1//! A from-scratch toolkit to parse, edit, sign, verify, generate, validate and
2//! render PDFs.
3//!
4//! This facade is the public API; the `otf-pdf-*` crates behind it are
5//! internal and may change freely. See the
6//! [API guide](https://github.com/Open-Tech-Foundation/PDF/blob/main/docs/API.md)
7//! for a tour by task, and the
8//! [embedding guide](https://github.com/Open-Tech-Foundation/PDF/blob/main/docs/EMBEDDING.md)
9//! for threading, limits and errors.
10//!
11//! Input is read through the [`Source`] trait, so the caller decides where
12//! bytes come from; this crate does no I/O of its own.
13//!
14//! ```
15//! # let bytes = b"%PDF-1.7\n1 0 obj << /Type /Catalog /Pages 2 0 R >> endobj\n\
16//! #   2 0 obj << /Type /Pages /Kids [3 0 R] /Count 1 >> endobj\n\
17//! #   3 0 obj << /Type /Page /Parent 2 0 R >> endobj\n".to_vec();
18//! use otf_pdf::{Document, OpenOptions};
19//!
20//! let doc = Document::open(bytes, OpenOptions::default())?;
21//! assert_eq!(doc.page_count()?, 1);
22//! // That file has no xref; the repair is recorded, not hidden.
23//! assert!(!doc.diagnostics().is_empty());
24//! # Ok::<(), otf_pdf::Error>(())
25//! ```
26#![forbid(unsafe_code)]
27
28pub use otf_pdf_doc::{
29    Attachment, AttachmentOptions, Document, Encryption, Info, OutlineItem, Page, Rect,
30    SanitizeOptions, SanitizeReport, SaveMode, SaveOptions, Store, decode_text_string,
31    encode_text_string,
32};
33pub use otf_pdf_text::{PageText, TextChar, TextExtractor, TextLine, Word};
34/// Content-stream interpretation: run a page through your own
35/// [`Device`](content::Device).
36pub mod content {
37    pub use otf_pdf_content::{
38        Device, FillRule, Font, FontLoader, Glyph, GraphicsState, Image, Matrix, Operation,
39        PathSegment, TextState, page_content, parse_content, run_page,
40    };
41    pub use otf_pdf_font::FontCache;
42}
43pub use otf_pdf_syntax::crypt::{Authentication, CryptMethod, SecurityHandler};
44pub use otf_pdf_syntax::serialize::{to_bytes, write_object};
45pub use otf_pdf_syntax::xref::XrefEntry;
46pub use otf_pdf_syntax::{
47    Budget, Diagnostic, DiagnosticKind, Dict, Entropy, Error, File, HEADER_SEARCH_WINDOW, Header,
48    HeaderError, LimitKind, Limits, Name, ObjId, Object, OpenOptions, PdfString, Permissions,
49    Result, Sink, Source, SourceError, Stream, Strictness, Version, find_header,
50};
51
52#[cfg(test)]
53mod tests {
54    use super::*;
55
56    /// Embedders move documents and errors across threads (a host's
57    /// blocking pool, docs/EMBEDDING.md); this fails to compile if any
58    /// public type stops being shareable.
59    #[test]
60    fn public_types_are_send_and_sync() {
61        const fn shareable<T: Send + Sync>() {}
62        shareable::<Document>();
63        shareable::<File>();
64        shareable::<OpenOptions>();
65        shareable::<Limits>();
66        shareable::<Error>();
67        shareable::<Page>();
68        shareable::<Object>();
69        shareable::<Diagnostic>();
70        shareable::<SecurityHandler>();
71        shareable::<SaveOptions>();
72        shareable::<Store>();
73        shareable::<PageText>();
74    }
75
76    #[test]
77    fn one_document_is_read_from_many_threads() {
78        let bytes = b"%PDF-1.7\n1 0 obj << /Type /Catalog /Pages 2 0 R >> endobj\n\
79            2 0 obj << /Type /Pages /Kids [3 0 R 4 0 R] /Count 2 >> endobj\n\
80            3 0 obj << /Type /Page /Parent 2 0 R >> endobj\n\
81            4 0 obj << /Type /Page /Parent 2 0 R >> endobj\n"
82            .to_vec();
83        let doc = std::sync::Arc::new(Document::open(bytes, OpenOptions::default()).unwrap());
84        let handles: Vec<_> = (0..4)
85            .map(|_| {
86                let doc = std::sync::Arc::clone(&doc);
87                std::thread::spawn(move || doc.page_count().unwrap())
88            })
89            .collect();
90        for h in handles {
91            assert_eq!(h.join().unwrap(), 2);
92        }
93    }
94}