vs Bibliotecas PDF para Rust
PDF Oxide comparado com as crates PDF para Rust mais usadas: lopdf, printpdf, pdf-rs e pdf_extract. Cada uma mira um nível de abstração diferente e um conjunto distinto de casos de uso.
Resumo
| PDF Oxide | lopdf | printpdf | pdf-rs | pdf_extract | |
|---|---|---|---|---|---|
| Nível da API | Alto nível | Baixo nível | Nível intermediário (criação) | Baixo nível (leitura) | Nível intermediário (leitura) |
| Ler PDFs | Sim | Sim | Não | Sim | Sim |
| Escrever PDFs | Sim | Sim | Sim | Não | Não |
| Extração de texto | Sim (alto nível) | Manual | Não | Manual | Sim (básica) |
| Extração de imagens | Sim (alto nível) | Manual | Não | Manual | Não |
| Campos de formulário | Leitura + escrita | Manual | Não | Apenas leitura | Não |
| Criação de PDF | Sim | Sim | Sim | Não | Não |
| Entrada Markdown/HTML | Sim | Não | Não | Não | Não |
| Editar PDFs existentes | Sim | Sim (baixo nível) | Não | Não | Não |
| Anotações | Leitura + escrita | Manual | Não | Apenas leitura | Não |
| Criptografia | Leitura + escrita | Não | Não | Não | Não |
| Validação PDF/A | Sim | Não | Não | Não | Não |
| Renderização | Sim (tiny-skia) | Não | Não | Parcial | Não |
| Bindings para Python | Sim | Não | Não | Não | Não |
| Licença | MIT | MIT | MIT | MIT | Apache-2.0 |
Todas as bibliotecas têm licenças permissivas. As diferenças estão no escopo e no nível de abstração.
Comparação de desempenho
Benchmark no corpus completo (3.830 PDFs)
Testado no corpus completo de 3.830 PDFs — três suítes de teste independentes e disponíveis publicamente, cobrindo conformidade com a especificação PDF (veraPDF, 2.907 arquivos), casos extremos de renderização em navegadores do mundo real (Mozilla pdf.js, 897 arquivos) e testes de estresse de segurança/robustez, incluindo estruturas malformadas e corrupção gerada por fuzzing (DARPA SafeDocs, 26 arquivos). Veja os detalhes do corpus completo.
| Biblioteca | Média | p99 | Taxa de sucesso | Extração de texto | Observações |
|---|---|---|---|---|---|
| PDF Oxide | 0,8ms | 9ms | 100% | Integrada, de nível de produção | Unicode, CJK, ordem de leitura |
| oxidize_pdf | 13,5ms | 11ms | 99,1% | Básica | Outlier máximo de 48s |
| unpdf | 2,8ms | 10ms | 95,1% | Básica | 185 falhas no corpus completo |
| pdf_extract | 4,08ms | 37ms | 91,5% | Básica | Perde layouts complexos |
| lopdf | 0,3ms | 2ms | 80,2% | Sem extração integrada | Falha em 20% dos PDFs |
A lopdf é mais rápida nos PDFs que consegue analisar — mas falha em 20% do corpus e não oferece extração de texto. Você teria que construir por conta própria a decodificação de fontes, a resolução de CMap e a análise de espaçamento.
A pdf_extract oferece extração de texto básica, mas tem taxa de sucesso de 91,5% e tem dificuldades com layouts complexos, texto CJK e PDFs marcados. A oxidize_pdf tem confiabilidade razoável (99,1%), mas é 17× mais lenta que a pdf_oxide no tempo médio de extração, com um outlier de pior caso de 48 segundos. A unpdf processa o corpus completo, mas falha em 185 PDFs.
PDF Oxide é a única crate Rust que combina 100% de confiabilidade com extração de texto de nível de produção.
Comparação de design da API
PDF Oxide: alto nível, orientada a tarefas
PDF Oxide oferece métodos criados especificamente para tarefas comuns. Você trabalha com texto, imagens e campos de formulário — não com objetos e dicionários PDF.
use pdf_oxide::PdfDocument;
let mut doc = PdfDocument::open("report.pdf")?;
// Text extraction -- one call
let text = doc.extract_text(0)?;
println!("{}", text);
// Styled spans with font metadata
let spans = doc.extract_spans(0)?;
for span in &spans {
println!("'{}' font={} size={:.1}pt", span.text, span.font_name, span.font_size);
}
// Image extraction
let images = doc.extract_images(0)?;
for img in &images {
println!("{}x{} {:?}", img.width, img.height, img.format);
}
// Form fields
let fields = doc.extract_form_fields()?;
for field in &fields {
println!("{}: {:?}", field.name, field.value);
}
A criação de PDF é igualmente direta:
use pdf_oxide::api::Pdf;
// From Markdown
let pdf = Pdf::from_markdown("# Report\n\n| A | B |\n|---|---|\n| 1 | 2 |")?;
pdf.save("report.pdf")?;
// From HTML
let pdf = Pdf::from_html("<h1>Report</h1><p>Content here.</p>")?;
pdf.save("report.pdf")?;
lopdf: manipulação de objetos em baixo nível
A lopdf dá acesso direto a objetos PDF, streams e à tabela de referências cruzadas. Você precisa entender a especificação PDF para usá-la de forma eficaz. Não há extração de texto integrada — você navega pelos dicionários e decodifica os streams por conta própria.
use lopdf::Document;
let doc = Document::load("report.pdf")?;
// Get page dictionary
let page_id = doc.page_iter().next().unwrap();
let page = doc.get_dictionary(page_id)?;
// Get content stream -- manual work
let contents = page.get("Contents")?;
let stream = doc.get_object(contents.as_reference()?)?;
// To extract text you must:
// 1. Parse the content stream operators
// 2. Resolve font references from /Resources
// 3. Decode CMap/ToUnicode mappings
// 4. Apply text matrix transformations
// 5. Handle encoding differences
//
// lopdf does not provide any of this -- it is raw object access
println!("Page has {} objects", doc.objects.len());
A lopdf é a ferramenta certa quando você precisa manipular a estrutura do PDF diretamente: mesclar documentos, reescrever streams de objetos ou construir processadores de PDF especializados.
printpdf: apenas criação de PDF
A printpdf é uma biblioteca somente de criação. Ela não consegue ler nem analisar PDFs existentes. Oferece uma API tipada para construir documentos PDF do zero, com texto, imagens e gráficos vetoriais.
use printpdf::*;
let (doc, page1, layer1) = PdfDocument::new(
"Report", Mm(210.0), Mm(297.0), "Layer 1"
);
let current_layer = doc.get_page(page1).get_layer(layer1);
// Add text -- requires manual font loading
let font = doc.add_builtin_font(BuiltinFont::Helvetica)?;
current_layer.use_text("Hello World", 24.0, Mm(10.0), Mm(280.0), &font);
// Save
doc.save(&mut std::io::BufWriter::new(
std::fs::File::create("output.pdf")?,
))?;
// Cannot read existing PDFs
// Cannot extract text, images, or form fields
A printpdf é a ferramenta certa quando você só precisa gerar novos PDFs e quer uma API de criação limpa e focada.
pdf-rs: leitura de PDF em baixo nível
A pdf-rs analisa a estrutura do PDF em tipos Rust, mas oferece funcionalidade de alto nível mínima. Você obtém acesso tipado aos objetos PDF, mas ainda precisa lidar com a decodificação de texto, a resolução de fontes e a análise de streams de conteúdo.
use pdf::file::FileOptions;
let file = FileOptions::cached().open("report.pdf")?;
// Access page objects
let page = file.get_page(0)?;
let media_box = page.media_box()?;
println!("Page size: {:?}", media_box);
// Content stream access -- low-level
if let Some(ref contents) = page.contents {
// Returns raw operations -- you must interpret them
// No built-in text assembly, font decoding, or layout analysis
}
// Cannot write or modify PDFs
A pdf-rs é a ferramenta certa quando você precisa de um parser de PDF type-safe para análise, validação ou para construir um renderizador personalizado.
Comparação de recursos por tarefa
Extração de texto
| Biblioteca | Integrada | Qualidade | Esforço necessário |
|---|---|---|---|
| PDF Oxide | Sim | Nível de produção (Unicode, CJK, ordem de leitura) | Uma chamada de método |
| pdf_extract | Sim | Básica (perde layouts complexos) | Uma chamada de método |
| lopdf | Não | N/D | Centenas de linhas de código personalizado |
| printpdf | Não | N/D | Impossível (somente escrita) |
| pdf-rs | Não | N/D | Exige código personalizado significativo |
PDF Oxide trata da decodificação CMap/ToUnicode, do espaçamento baseado em métricas de fonte, da ordem de leitura pela árvore de estrutura e da reconstrução de ligaduras. Implementar funcionalidade equivalente sobre a lopdf ou a pdf-rs exige milhares de linhas de código e profundo conhecimento da especificação PDF.
Criação de PDF
| Biblioteca | Abordagem | Entrada Markdown/HTML | Tabelas | Códigos de barras |
|---|---|---|---|---|
| PDF Oxide | Alto nível + baixo nível | Sim | Sim | Sim |
| lopdf | Construção de objetos crus | Não | Não | Não |
| printpdf | API tipada de camadas | Não | Não | Não |
| pdf-rs | N/D (somente leitura) | N/D | N/D | N/D |
Criptografia
| Biblioteca | Ler criptografado | Escrever criptografado | Algoritmos |
|---|---|---|---|
| PDF Oxide | Sim | Sim | RC4-40, RC4-128, AES-128, AES-256 |
| lopdf | Não | Não | – |
| printpdf | Não | Não | – |
| pdf-rs | Parcial | Não | Apenas RC4 |
Conformidade
| Biblioteca | PDF/A | PDF/X | PDF/UA |
|---|---|---|---|
| PDF Oxide | Validar + converter | Validar | Validar |
| lopdf | Não | Não | Não |
| printpdf | Parcial (saída PDF/A-1b) | Não | Não |
| pdf-rs | Não | Não | Não |
Pegada de dependências
| Biblioteca | Dependências | Tempo de compilação | Tamanho do binário |
|---|---|---|---|
| PDF Oxide | ~40 (núcleo) | ~30s | ~4 MB |
| lopdf | ~15 | ~10s | ~1 MB |
| printpdf | ~20 | ~15s | ~2 MB |
| pdf-rs | ~25 | ~20s | ~2 MB |
PDF Oxide tem mais dependências porque inclui análise de fontes, decodificação de imagens, interpretação de streams de conteúdo e criptografia — recursos que as outras bibliotecas deixam a cargo do usuário ou omitem por completo. Com todos os recursos opcionais (rendering, barcodes, office), o número sobe para ~100.
Combinando bibliotecas
Como todas têm licenças permissivas, você pode combiná-las em um único projeto:
[dependencies]
pdf_oxide = "0.3"
lopdf = "0.32" # Optional: raw object access for edge cases
Padrões comuns:
- PDF Oxide + lopdf: use PDF Oxide para extração e criação, recorrendo à lopdf nos casos extremos que exigem manipulação de objetos crus.
- PDF Oxide + printpdf: use PDF Oxide para leitura e printpdf para fluxos de criação especializados.
Matriz de casos de uso
“Preciso extrair texto de PDFs”
| Crate | Adequada? | Observações |
|---|---|---|
| PDF Oxide | Sim | Melhor qualidade de extração, 100% de taxa de sucesso, ordem de leitura, metadados de fonte |
| pdf_extract | Parcial | Extração básica, 91,5% de taxa de sucesso |
| lopdf | Não | Sem extração de texto |
| printpdf | Não | Não consegue ler PDFs |
| pdf-rs | Parcial | Análise básica, sem extração de texto de alto nível |
“Preciso criar PDFs”
| Crate | Adequada? | Observações |
|---|---|---|
| PDF Oxide | Sim | APIs de alto nível (Markdown/HTML) e de baixo nível |
| lopdf | Parcial | Construção de objetos em baixo nível |
| printpdf | Sim | API de criação limpa, sem leitura |
| pdf-rs | Não | Somente leitura |
“Preciso editar PDFs existentes”
| Crate | Adequada? | Observações |
|---|---|---|
| PDF Oxide | Sim | Edição estilo DOM, anotações, formulários |
| lopdf | Parcial | Manipulação de objetos em baixo nível |
| printpdf | Não | Não consegue ler PDFs |
| pdf-rs | Não | Somente leitura |
“Preciso do ciclo de vida completo (extrair + criar + editar)”
| Crate | Adequada? | Observações |
|---|---|---|
| PDF Oxide | Sim | Única crate que cobre os três |
| lopdf + printpdf | Parcial | Duas crates, sem extração de texto |
| pdf-rs + printpdf | Parcial | Duas crates, sem edição |
Quando usar cada uma
Escolha PDF Oxide se você precisa de mais de uma capacidade de PDF (extração + criação, ou extração + edição) e quer uma única dependência bem testada com 100% de confiabilidade.
Escolha lopdf se você precisa de manipulação da estrutura do PDF em baixo nível e está confortável em trabalhar diretamente com a especificação PDF. Boa para mesclagem, divisão e processamento em lote de PDFs.
Escolha printpdf se você só cria PDFs e nunca precisa lê-los. A API mais limpa para geração de relatórios e documentos.
Escolha pdf-rs se você precisa de um parser em conformidade com a especificação para análise de PDF ou está construindo seu próprio pipeline de renderização.
Escolha pdf_extract se você precisa de extração de texto básica e não exige alta confiabilidade nem suporte a layouts complexos.
Páginas relacionadas
- Benchmarks de desempenho – resultados do benchmark no corpus completo
- Primeiros passos com Rust – instalação e primeira extração
- Referência da API Rust – API Rust completa
- vs Bibliotecas PDF para Python – comparação do ecossistema Python