In questa sezione

Cartucce di elaborazione dei documenti: PDF, testo e i pattern di cap standard che usano.

Architettura delle cartucce di contenuto

Le cartucce di contenuto sono più semplici delle cartucce di modelli:

  • Nessuna chiamata peer; tutta l’elaborazione è autonoma.
  • Nessun caricamento di modelli né keepalive; le operazioni si completano rapidamente.
  • Implementazioni degli handler più brevi, di solito sotto le 100 righe ciascuna.
  • Usano gli helper standard per i cap URN di capdag::standard::caps.

Il pattern degli handler è: ricevi l’input → elabora → emetti l’output. Nessuna architettura in tre fasi, nessuna gestione dei thread FFI.

Sorgente: pdfcartridge, txtcartridge.

Cap standard

graph LR
    PDF["media:document;ext=pdf"] -->|generate_thumbnail| IMG["media:ext=png;image"]
    PDF -->|extract_metadata| REC["media:record"]
    PDF -->|extract_outline| JSON["media:json"]
    PDF -->|disbind| LIST["media:document;ext=pdf;list"]

    TXT["media:enc=utf-8"] -->|generate_thumbnail| IMG2["media:ext=png;image"]
    TXT -->|extract_metadata| REC2["media:record"]
    MD["media:enc=utf-8;ext=md"] -->|extract_outline| JSON2["media:fmt=json;record"]

capdag::standard::caps definisce helper per i cap URN delle operazioni comuni sui documenti:

Funzione Operazione Descrizione
generate_thumbnail_urn(media) generate;target=thumbnail Genera un’anteprima visiva dell’input.
extract_metadata_urn(media) extract;target=metadata Estrae metadati strutturati (titolo, autore, numero di pagine, date).
extract_outline_urn(media) extract;target=outline Estrae la struttura del documento o l’indice.
disbind_urn(media) op=disbind Estrae singole pagine o sezioni come elementi separati.

Ogni funzione prende un media URN (per esempio "media:document;ext=pdf") e restituisce la stringa del cap URN per quell’operazione su quel tipo di media. Il cap URN include le specifiche in= e out= appropriate.

Sorgente: capdag-rs/src/standard/caps.rs.

pdfcartridge

Fornisce quattro cap per i documenti PDF:

generate_thumbnail

Rende le pagine PDF come miniature PNG. Argomenti:

  • media:document;ext=pdf (obbligatorio, stdin): il documento PDF.
  • media:width;enc=utf-8;numeric (facoltativo): larghezza dell’output in pixel.
  • media:height;enc=utf-8;numeric (facoltativo): altezza dell’output in pixel.
  • media:index-range;enc=utf-8 (facoltativo): quali pagine rendere (per esempio “0-2” per le prime tre pagine).

extract_metadata

Estrae i metadati del PDF come JSON. Restituisce un record con titolo, autore, oggetto, creatore, data di creazione, data di modifica, numero di pagine e altre proprietà del documento.

Argomenti: media:document;ext=pdf (obbligatorio, stdin).

extract_outline

Estrae la struttura del PDF (segnalibri/indice) come struttura JSON gerarchica. Argomenti:

  • media:document;ext=pdf (obbligatorio, stdin).
  • media:max-depth;enc=utf-8;numeric (facoltativo): profondità massima di attraversamento della struttura.
  • media:include-order-indexes;enc=utf-8 (facoltativo): se includere gli indici di ordinamento.

disbind

Estrae le singole pagine del PDF come elementi separati. Usa emit_list_item() per inviare le pagine in streaming una alla volta:

output.start(true, input_meta.clone())?;
for (i, page_bytes) in pages.iter().enumerate() {
    output.progress(i as f32 / pages.len() as f32, &format!("Page {}", i + 1));
    output.emit_list_item(&ciborium::Value::Bytes(page_bytes.to_vec()), None).await?;
}

Sorgente: pdfcartridge/src/main.rs.

txtcartridge

Fornisce l’estrazione di miniature, metadati e struttura per i formati basati su testo: testo semplice (.txt), reStructuredText (.rst), file di log (.log) e Markdown (.md).

Le stesse implementazioni degli handler sono registrate per tutti e quattro i tipi di media. L’estrazione della struttura è disponibile soltanto per i formati di testo strutturati (Markdown, reStructuredText), in cui i titoli definiscono la struttura del documento.

Pattern dell’handler multi-tipo

Un singolo handler serve più tipi di media provando ciascun URN noto:

fn require_text_content(streams: &[(String, Vec<u8>)]) -> Result<&[u8], StreamError> {
    for urn in &[MEDIA_TXT, MEDIA_RST, MEDIA_LOG, MEDIA_MD] {
        if let Some(bytes) = find_stream(streams, urn) {
            return Ok(bytes);
        }
    }
    Err(StreamError::Protocol("No recognized text stream found".to_string()))
}

La registrazione itera su tutti i tipi di media:

for media in &[MEDIA_TXT, MEDIA_RST, MEDIA_LOG, MEDIA_MD] {
    runtime.register_op(&generate_thumbnail_urn(media), || Box::new(ThumbnailOp));
    runtime.register_op(&extract_metadata_urn(media), || Box::new(MetadataOp));
}

// Struttura soltanto per i formati strutturati
for media in &[MEDIA_MD, MEDIA_RST] {
    runtime.register_op(&extract_outline_urn(media), || Box::new(OutlineOp));
}

Il dispatch dei cap URN (vedi Dispatch) garantisce che la richiesta in arrivo corrisponda esattamente a uno dei tipi di media registrati. Il ciclo di ripiego dell’handler sugli URN trova lo stream corrispondente.

Sorgente: txtcartridge/src/main.rs.

Costruire una cartuccia di contenuto

Per aggiungere una nuova cartuccia di contenuto per un ipotetico tipo di media (per esempio EPUB):

  1. Crea il crate: imposta un crate binario Rust con #[tokio::main] e dipendenze da capdag e ops.

  2. Definisci i cap URN: usa gli helper standard o costruiscine di personalizzati:
    let thumb_cap = make_cap(generate_thumbnail_urn("media:document;ext=epub"));
    let meta_cap = make_cap(extract_metadata_urn("media:document;ext=epub"));
    
  3. Costruisci il manifest: includi identity_cap() e tutte le tue cap:
    let manifest = CapManifest::new(
        "epubcartridge".to_string(),
        "1.0.0".to_string(),
        "EPUB document processing".to_string(),
        vec![identity_cap(), thumb_cap, meta_cap],
    );
    
  4. Implementa gli handler: ogni handler implementa Op<()>. Vedi Pattern degli handler per i pattern standard.

  5. Registra ed esegui:
    let mut runtime = CartridgeRuntime::with_manifest(manifest);
    runtime.register_op(&generate_thumbnail_urn("media:document;ext=epub"), || Box::new(ThumbnailOp));
    runtime.register_op(&extract_metadata_urn("media:document;ext=epub"), || Box::new(MetadataOp));
    runtime.run().await?;
    

Usa pdfcartridge come implementazione di riferimento; dimostra tutte e quattro le operazioni standard con codice degli handler pulito.