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::Document;

fn main() -> pdfluent::Result<()> {
    let doc = Document::open("archive.pdf")?;

    match doc.pdf_a_level() {
        Some(level) => println!("Claimed level: {:?}", level),
        None => println!("No PDF/A claim in XMP metadata"),
    }

    let report = doc.validate_pdf_a()?;
    if report.is_conformant() {
        println!("Validation passed.");
    } else {
        for err in report.errors() {
            println!("Error: {}", err.message());
        }
    }

    Ok(())
}
Install:cargo add pdfluentDownload SDK →

Step by step

1

Open the document

Read-only access is sufficient for conformance checking.

rust
let doc = Document::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::pdfa::PdfALevel;

match doc.pdf_a_level() {
    Some(PdfALevel::A1b) => println!("PDF/A-1b"),
    Some(PdfALevel::A1a) => println!("PDF/A-1a"),
    Some(PdfALevel::A2b) => println!("PDF/A-2b"),
    Some(PdfALevel::A2a) => println!("PDF/A-2a"),
    Some(PdfALevel::A2u) => println!("PDF/A-2u"),
    Some(PdfALevel::A3b) => println!("PDF/A-3b"),
    None                 => println!("Not PDF/A"),
}
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_pdf_a()?;
println!("Conformant: {}", report.is_conformant());
println!("Errors: {}", report.error_count());
println!("Warnings: {}", report.warning_count());
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 err in report.errors() {
    println!(
        "[{}] {} (obj {})",
        err.rule_id(),
        err.message(),
        err.object_number().map_or("?".to_string(), |n| n.to_string()),
    );
}
5

Validate against a specific level

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

rust
use pdfluent::pdfa::PdfALevel;

let report = doc.validate_pdf_a_level(PdfALevel::A2b)?;

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