easypdf-core 0.1.1

Core types, traits, enums, converters, and errors for easypdf-rust
Documentation

easypdf-core

Foundation layer for easypdf-rust: core traits, types, IO safety primitives, PDF crypto (encrypt/sign), and Markdown IR.

Role

easypdf-core is the lowest-level crate in the easypdf-rust workspace. It defines the shared abstractions that every upper-layer crate (reader, writer, markdown, ocr, runtime) depends on: core traits, content types, enums, error types, IO guards, encryption, digital signatures, and the semantic document model (PdfBlock / PdfDocumentModel).

Core Capabilities

  • Core traits (PdfModel, PdfReadListener, PdfWriteHandler, PdfConverter, PdfEngine) -- extension points for reading, writing, and conversion (crates/easypdf-core/src/traits.rs)
  • Content model (PdfText, PdfTable, PdfImage, PdfLine, PdfRect) -- semantic content elements (crates/easypdf-core/src/content.rs)
  • Document IR (PdfDocumentModel, PdfPageModel, PdfBlock with 14 variants) -- structured intermediate representation (crates/easypdf-core/src/model/)
  • IO safety (PdfInput, ResourceLimits, AtomicFileOutput, guard_decompression_bomb, guard_element_explosion) -- resource limits, SSRF protection, crash-safe writes (crates/easypdf-core/src/io/)
  • PDF encryption (AES-128/256, ISO 32000) -- encrypt_pdf() / decrypt_pdf() with 8 permission flags (crates/easypdf-core/src/crypto/encrypt.rs)
  • PDF signing (PKCS#7/CMS, RSA-PKCS#1v1.5 + SHA-256 via ring) -- sign_pdf() / verify_pdf_signature() (crates/easypdf-core/src/crypto/sign.rs)
  • Style & metadata (PdfFont, PdfColor, BuiltInFont, TableStyle, PdfMetadata, PdfBookmark) -- (crates/easypdf-core/src/style.rs, crates/easypdf-core/src/metadata.rs)
  • Layout engine (FlowLayout, LayoutSink, Direction) -- flow-based layout infrastructure (crates/easypdf-core/src/layout/)

Dependencies

Internal

None -- this is the foundation crate.

External

Crate Version Purpose
lopdf 0.44.0 PDF object model (encrypt/decrypt via lopdf API)
ring 0.17 Constant-time RSA operations for signing
aes / cbc / cipher -- AES encryption primitives
x509-parser 0.16 X.509 certificate parsing
bitflags 2 PdfPermissions bitflags
thiserror 2.0.18 Error type derivation
chrono 0.4.45 Date/time handling
serde / serde_json 1.x Serialization

Main API

Enums

// Page & layout
pub enum PageSize { A0, A1, A2, A3, A4, A5, Letter, Legal, Custom(f64, f64) }
pub enum Orientation { Portrait, Landscape }
pub enum Rotation { None, Clockwise90, Clockwise180, Clockwise270 }
pub enum TextAlignment { Left, Center, Right, Justify }
pub enum VerticalAlignment { Top, Middle, Bottom }
pub enum ImageFormat { Jpeg, Png }

// Content block (#[non_exhaustive], 14 variants)
pub enum PdfBlock {
    Heading { level: u8, text: String, source: SourceLocation },
    Paragraph { text: String, source: SourceLocation },
    List { ordered: bool, items: Vec<ListItem>, source: SourceLocation },
    Table { headers: Vec<String>, rows: Vec<Vec<String>>, source: SourceLocation },
    Image { data: ImageData, source: SourceLocation },
    Code { language: Option<String>, text: String, source: SourceLocation },
    // ... 8 more variants
}

// Crypto
pub enum PdfEncryptionAlgorithm { Aes128, Aes256 }

Traits

pub trait PdfModel {
    fn render(&self) -> Result<Vec<RenderedElement>>;
    fn metadata(&self) -> PdfModelMetadata;
    fn field_descriptors(&self) -> Vec<PdfFieldDescriptor>;
}

pub trait PdfReadListener: Send {
    fn on_page_start(&mut self, page: PageNumber) -> Result<()>;
    fn on_text(&mut self, page: PageNumber, text: &str) -> Result<()>;
    fn on_page_end(&mut self, page: PageNumber) -> Result<()>;
    fn on_document_end(&mut self) -> Result<()>;
}

pub trait PdfWriteHandler: Send {
    fn before_document(&mut self) -> Result<()> { Ok(()) }
    fn before_page(&mut self, page: PageNumber) -> Result<()> { Ok(()) }
    fn after_page(&mut self, page: PageNumber) -> Result<()> { Ok(()) }
    fn after_document(&mut self) -> Result<()> { Ok(()) }
}

pub trait PdfEngine: Send + Sync {
    fn name(&self) -> &str;
    fn capabilities(&self) -> EngineCapabilities;
}

Content Builders

let text = PdfText::new("Hello")
    .font(PdfFont::helvetica(12.0))
    .alignment(TextAlignment::Center)
    .color(PdfColor::red());

let table = PdfTable::new(vec!["Name".into(), "Age".into()])
    .row(vec!["Alice".into(), "30".into()])
    .width(400.0);

Encryption & Signing

use easypdf_core::crypto::{encrypt_pdf, decrypt_pdf};

let enc = PdfEncryption::new("user", "owner")
    .with_algorithm(PdfEncryptionAlgorithm::Aes256)
    .with_permissions(PdfPermissions::PRINT | PdfPermissions::COPY);
let encrypted = encrypt_pdf(&pdf_bytes, &enc)?;

// Signing
use easypdf_core::crypto::{sign_pdf, verify_pdf_signature};
sign_pdf(&pdf_bytes, &signer)?;
let info = verify_pdf_signature(&pdf_bytes)?;

IO Safety

let input = PdfInput::from_path("doc.pdf");
let limits = ResourceLimits::default(); // 50 MB, 10000 pages
let bytes = input.read(limits)?;

// Atomic writes
let out = AtomicFileOutput::new("output.pdf");
out.write_all(&pdf_bytes)?; // writes to temp, renames on success

Known Limitations

  • RFC 3161 timestamp server support: fields reserved but not yet implemented (crates/easypdf-core/src/crypto/sign.rs:69)
  • PdfEngine trait defined but no concrete implementation yet (crates/easypdf-core/src/traits.rs:260-263)
  • unsafe_code = "forbid" enforced workspace-wide

License

Apache-2.0


Project: https://github.com/easy-4-rust/easypdf-rust crates.io: https://crates.io/crates/easypdf-core docs.rs: https://docs.rs/easypdf-core