Generación de PDF en Rust: revisión de bibliotecas y ejemplos prácticos
Rust es un lenguaje de programación de sistemas que se utiliza cada vez más para crear aplicaciones de servidor de alto rendimiento, servicios web y herramientas de línea de comandos. Una de las tareas comunes al desarrollar estos proyectos es la generación de documentos PDF: informes, facturas, certificados o simplemente archivos de texto con formato. En este artículo, revisaremos las principales bibliotecas para trabajar con PDF en Rust, sus capacidades, ejemplos de código y criterios de selección.
Bibliotecas populares para la generación de PDF en Rust
Actualmente, en el ecosistema de Rust se pueden destacar tres bibliotecas principales que son activamente mantenidas y utilizadas por la comunidad:
- printpdf — una biblioteca de bajo nivel para crear documentos PDF con control total sobre el contenido. Soporta texto, imágenes, gráficos vectoriales, tablas e incrustación de fuentes.
- genpdf — una biblioteca de nivel superior, construida sobre printpdf. Proporciona abstracciones convenientes para trabajar con texto, párrafos, tablas y estilos.
- pdf_writer — otra biblioteca de bajo nivel que se centra en el minimalismo y el rendimiento. Permite escribir archivos PDF directamente, pero requiere un conocimiento profundo del formato PDF.
Biblioteca printpdf
printpdf es una de las bibliotecas más populares para la generación de PDF en Rust. Proporciona una API para trabajar con primitivas gráficas, texto y fuentes. Las principales capacidades son:
- Creación de documentos de varias páginas;
- Incrustación de fuentes TrueType/OpenType;
- Dibujo de líneas, rectángulos, círculos y otras figuras;
- Inserción de imágenes (PNG, JPEG);
- Trabajo con colores y transparencia;
- Soporte para Unicode y cirílico.
Ejemplo de creación de un PDF simple con texto usando printpdf:
use printpdf::*;use std::fs::File;use std::io::BufWriter;
fn main() { // Creamos un documento en formato A4 let (doc, page1, layer1) = PdfDocument::new( "Ejemplo de PDF en Rust", Mm(210.0), Mm(297.0), "Layer 1", );
// Obtenemos la fuente actual (Helvetica incorporada) let font = doc.add_builtin_font(BuiltinFont::Helvetica).unwrap();
// Usamos la capa para dibujar let layer = doc.get_page(page1).get_layer(layer1);
// Añadimos texto layer.use_text("¡Hola, mundo! PDF desde Rust", 24.0, Mm(50.0), Mm(250.0), &font);
// Guardamos el archivo let file = File::create("hello.pdf").unwrap(); let writer = BufWriter::new(file); doc.save(&mut std::io::BufWriter::new(writer)).unwrap();}Biblioteca genpdf
genpdf es un envoltorio sobre printpdf que proporciona una API de más alto nivel. Es ideal para crear documentos con formato simple: encabezados, párrafos, listas, tablas. Las principales ventajas son:
- Gestión automática de saltos de página;
- Soporte para estilos (negrita, cursiva, subrayado);
- Soporte incorporado para tablas con celdas y bordes;
- Interfaz simple para añadir elementos.
Ejemplo de creación de un PDF con una tabla usando genpdf:
use genpdf::*;use genpdf::elements::*;use std::fs::File;
fn main() { // Creamos un documento let mut doc = Document::new("Liberation Serif") .expect("Error al cargar la fuente");
// Configuración del estilo por defecto doc.set_title("Informe de ventas");
// Añadimos un párrafo doc.push(Paragraph::new("Ventas por mes:"));
// Creamos una tabla let mut table = Table::new(vec![2, 3, 2]); table.set_cell_border_style(BorderStyle::Solid); table.push_row(vec![ "Mes".to_string(), "Ingresos, RUB".to_string(), ]);
// Añadimos la tabla al documento doc.push(table);
// Renderizamos y guardamos doc.render_to_file("reporte.pdf").expect("Error al guardar el PDF");}