How-to guides/PDF/A & Archiving

Detect the PDF/A conformance level of a document in Rust

Read the XMP metadata to determine whether a PDF claims PDF/A-1, 2, or 3 conformance, and run a structural validation check.

rust
use pdfluent::{PdfDocument, PdfAProfile};

fn main() -> pdfluent::Result<()> {
    let doc = PdfDocument::open("invoice.pdf")?;
    let report = doc.validate_pdfa(PdfAProfile::A2b)?;
    println!("compliant: {}", report.is_compliant());
    Ok(())
}

Step by step

1

Open the document

Read-only access is sufficient for conformance checking.

rust
let doc = PdfDocument::open("archive.pdf")?;
2

Read the claimed PDF/A level from XMP

pdf_a_level() inspects the pdfaid:part and pdfaid:conformance XMP fields. It returns the declared level, not a validated one.

rust
use pdfluent::PdfAProfile;

let report = doc.validate_pdfa(PdfAProfile::A2b)?;
println!("PDF/A-2b compliant: {}", report.is_compliant());
3

Run a structural validation

validate_pdf_a() checks the rules for the claimed level: embedded fonts, no encryption, no transparency (A-1), color spaces, output intent, and XMP metadata.

rust
let report = doc.validate_pdfa(PdfAProfile::A2b)?;
println!("Compliant: {}", report.is_compliant());
println!("Violations: {}", report.violations.len());
4

Print detailed validation errors

Each ValidationError carries a rule ID (e.g. "6.3.3-1"), a human-readable message, and optionally the object number of the offending PDF object.

rust
for v in &report.violations {
    println!("[{}] {} (page {:?})", v.rule, v.message, v.page);
}
5

Validate against a specific level

To validate against a target level regardless of the XMP claim, pass it explicitly.

rust
use pdfluent::PdfAProfile;

// Validate against a specific profile (A1b, A2b, or A3b)
let report = doc.validate_pdfa(PdfAProfile::A1b)?;
println!("A1b compliant: {}", report.is_compliant());

Notes and tips

  • A PDF can claim PDF/A compliance in its XMP metadata but still fail structural validation. Always run validate_pdf_a() rather than relying on the XMP claim alone.
  • PDF/A-1b requires all fonts embedded; PDF/A-1a additionally requires tagged structure (logical reading order).
  • Transparency is forbidden in PDF/A-1 but allowed in PDF/A-2 and later. Flattening transparency is required for A-1 compliance.
  • The output intent (ICC color profile) is mandatory for all PDF/A levels. Use add_pdf_a_output_intent() to add one.

Why PDFluent for this

Pure Rust

No JVM, no runtime, no DLL dependencies. Ships as a single native binary or WASM module.

Memory safe

Rust's ownership model prevents buffer overflows and use-after-free. No segfaults in PDF parsing.

Runs anywhere

Same code runs server-side, in Docker, on AWS Lambda, on Cloudflare Workers, or in the browser via WASM.

Frequently asked questions