Struttura
Un media URN ha la forma:
media:<type>[;tag=value]...
Esempi:
media: # Identità (qualsiasi media)
media:document # Un documento, in qualsiasi formato
media:document;ext=pdf # Un PDF: un documento il cui formato è pdf
media:image # Un'immagine, in qualsiasi formato
media:ext=png;image # Un'immagine PNG
media:enc=utf-8 # Testo UTF-8 semplice (scalare per default)
media:fmt=json;record # Oggetto JSON (formato di serializzazione)
Tipo top e tipo unità
L’ordine dei media URN ha due ancore distinte. Non sono intercambiabili, e confonderle capovolge il significato di ogni cap che le usa.
media:: il tipo top
media:
Il solo prefisso, senza tag. Si legge “qualsiasi tipo di dati”.
- Non ha tag.
- Ogni altro media URN è
conforms_torispetto a esso. - Specificità 0.
- È il top dell’ordine parziale dei media.
pub const MEDIA_IDENTITY: &str = "media:";
∀m ∈ MediaUrn, m ⪯ media: (ogni media URN è conforme al top)
media: ⪯ media: (riflessivo)
Una cap con in=media: dice “accetto qualsiasi input”. Una cap con
out=media: dice “posso produrre qualsiasi output”. Usati su entrambi i lati,
sono semplicemente i tipi top del tutto generici per gli assi direzionali.
Da soli non significano identità.
Nel modello di cap a quattro assi:
cap:effect=noneè il morfismo identità esplicitocap:ecap:in=media:;out=media:sono forme top nude non ammessecap:<y-tags>con entrambi i lati direzionali amedia:è una trasformazione generica da top a top, non l’identità
media:void: il tipo unità
media:void
Si legge “nessun dato”: il valore nullario, il tipo con esattamente un abitante.
- Ha il tag marker
void. - È distinto da
media:. Top significa “qui scorre un qualsiasi A”; unit significa “qui scorre (), nessun payload significativo”.
pub const MEDIA_VOID: &str = "media:void";
Una cap con in=media:void non consuma dati; è guidata
interamente dai suoi tag non direzionali e da un eventuale stato del peer. Una cap con
out=media:void non produce dati; esiste per l’effetto collaterale.
Le cap con media:void su entrambi i lati sono puri comandi a effetto collaterale
(vedi CapKind: Source,
Sink, Effect).
Atomicità
media:void è atomico. Il parser rifiuta qualsiasi media URN che
combini il tag marker void con qualsiasi altro tag:
media:void ✓
media:void;text ✗ (errore di parsing)
media:void;pdf ✗ (errore di parsing)
media:void;reason=warmup ✗ (errore di parsing)
media:void;heartbeat ✗ (errore di parsing)
Sotto il tipo unità non c’è alcun reticolo. Ammettere raffinamenti
creerebbe una tassonomia fittizia di valori unit
(media:void;warmup contro media:void;heartbeat ecc.) e la semantica
del dispatch si biforcherebbe silenziosamente: sono unit diversi? effetti
diversi? comandi diversi? Rifiutare la sintassi chiude la
questione.
Quando una cap deve esprimere perché o come usa void, quell’informazione va sull’asse non direzionale del cap URN (o negli argomenti della cap), mai come raffinamento del media URN:
✓ cap:in=media:void;out=media:void;warmup
✓ cap:in=media:void;out=media:void;heartbeat
✓ cap:in=media:void;out=media:image;generate;target=thumbnail
✗ cap:in=media:void;reason=warmup;out=media:void
✗ cap:in=media:void;enc=utf-8;out=media:enc=utf-8
Ciascuna delle prime tre descrive un morfismo distinto (tag di operazione diversi). Le ultime due cercano di inserire la stessa distinzione nel tipo unità stesso; il parser le rifiuta al livello del media URN, prima ancora che il cap URN si formi.
Questa regola è applicata al livello più profondo: ogni costruttore di MediaUrn
e ogni percorso di parsing from_string restituisce un errore di parsing in caso di
violazione:
| Port | Errore |
|---|---|
| Rust | MediaUrnError::VoidNotAtomic |
| Go | MediaUrnError{Code: ErrorMediaVoidNotAtomic} |
| Python | MediaUrnError("media:void is atomic …") |
| Swift/ObjC | CSMediaUrnErrorVoidNotAtomic |
| JS | MediaUrnError(VOID_NOT_ATOMIC, …) |
Top e unit a colpo d’occhio
| Tipo del lato | Si legge | Usato per |
|---|---|---|
media: |
“qualsiasi A” | wildcard, passthrough generico |
media:void |
”()” | sorgenti, pozzi, effetti |
| concreto | un tipo specifico | normale flusso di dati |
media: e media:void sembrano superficialmente simili (entrambi sono
“non specifici” in un certo senso), ma stanno agli estremi opposti del
reticolo dei tipi. media: è il massimo dell’ordine; media:void
è una foglia che porta il valore nullario.
Marker semantici e i tre assi dei media
I media URN descrivono i dati con due tipi di tag: i tag marker che
dichiarano la modalità o la capacità numerica (numeric, image/visual,
audio), e tre assi del media URN ortogonali che descrivono come
i byte sono tipizzati, serializzati e codificati.
Non esiste alcun modello di coercizione. Una richiesta di media:enc=utf-8 corrisponde
solo a valori che portano il tag enc=utf-8; numeri, booleani e JSON
non vengono mai convertiti implicitamente in stringa. Adattare un valore da un formato a
un altro (numero → testo, JSON → CSV, testo → PDF) è compito di una
capacità di conversione esplicita (ad es. cap:convert-format), mai una
proprietà implicita del tipo. Il dispatch fa corrispondere i tipi così come sono dichiarati;
non applica coercizioni.
I tre assi dei media
| Asse | Tag | Descrive | A valore singolo? | Esempi |
|---|---|---|---|---|
| tipo di file | ext=<x> |
Il tipo di FILE su disco | no | pdf, png, txt, csv |
| formato dei dati | fmt=<x> |
Il formato di SERIALIZZAZIONE del contenuto | sì (≤ un fmt) |
json, yaml, ndjson, csv, xml, tsv, psv, cbor, msgpack |
| codifica | enc=<x> |
La CODIFICA dei caratteri del testo | sì | utf-8 |
Questi assi sono indipendenti e non devono essere confusi:
ext=è il modo in cui il file si chiama su disco; non dice nulla su come sono strutturati i byte.fmt=è il modo in cui il contenuto è serializzato, una volta guardato all’interno; un valore ha al massimo unfmt.enc=è la codifica dei caratteri, e la sua presenza è ciò che identifica il testo in quanto tale (vedi Rilevamento del tipo). Il testo semplice èmedia:enc=utf-8.
Quindi un file CSV su disco è media:ext=csv;fmt=csv;..., mentre il
contenuto CSV che scorre tra le cap è media:fmt=csv;list;record. Un
file di testo semplice è media:ext=txt;enc=utf-8; il testo semplice è soltanto
media:enc=utf-8.
Marker standard
| Tag | Significato | Esempi |
|---|---|---|
numeric |
Supporta operazioni numeriche | interi, float |
image |
Un’immagine, da guardare | png, jpeg, webp, un fotogramma video |
audio |
Audio, da ascoltare | wav, mp3, flac, frame PCM grezzi |
video |
Un video | mp4, mov, mkv, webm |
document |
Pagine impaginate, fogli o diapositive | pdf, docx, epub, xlsx |
image, audio, video e document sono i medium. Ciascuno è un
tipo a sé — media:image, media:audio, media:video,
media:document — e ogni formato di un medium porta il suo marker, così
media:ext=png;image è conforme a media:image e
media:document;ext=pdf a media:document. Una cap che prende qualsiasi immagine
dichiara media:image; una cap astratta su cap
per formato dichiara il medium che condividono. La scrittura tenuta come testo
(Markdown, RTF, HTML) è un file di testo e non porta alcun medium.
I marker sono ortogonali ai tre assi. Un numero è media:numeric
(senza enc=, perché non viene consegnato come testo). Un booleano consegnato come
testo è media:bool;enc=utf-8. Non esiste un marker binary:
tutto è binario a livello di byte, quindi “binario” non è una categoria.
La domanda significativa è quali assi porta un tipo.
L’adattamento di formato è esplicito
Una capacità che richiede media:enc=utf-8 corrisponde a valori che portano
effettivamente il tag enc=utf-8. Non corrisponde a un semplice media:numeric
né a media:fmt=json;record. Per passare un numero a una cap che consuma testo,
instradalo attraverso una cap di conversione esplicita:
media:numeric ──[cap:convert-format → text]──▶ media:enc=utf-8
media:fmt=json;record ──[cap:convert-format → csv]──▶ media:fmt=csv;list;record
La cap di conversione è un nodo reale del grafo, con i propri tipi di input e di output. Nulla viene adattato alle spalle del dispatcher.
Marker strutturali e valori predefiniti
I media URN non hanno un asse form=. La struttura è rappresentata da
tag marker e dall’assenza come valore predefinito:
| Proprietà di forma | Codifica | Significato |
|---|---|---|
| scalare | nessun tag list |
Valore singolo (cardinalità predefinita) |
| lista | marker list |
Collezione ordinata |
| opaco | nessun tag record |
Nessuna struttura interna chiave-valore (predefinito) |
| record | marker record |
Struttura chiave-valore |
Quindi:
media:enc=utf-8significa scalare + opaco (testo)media:fmt=json;recordsignifica scalare + recordmedia:enc=utf-8;listsignifica lista + opacomedia:fmt=json;list;recordsignifica lista + record
Esempi
media:enc=utf-8 # Stringa
media:enc=utf-8;list # Array di stringhe
media:fmt=json;record # Oggetto JSON
media:integer;list;numeric # Array di interi
Tipi di media comuni
Primitivi
| Media URN | Costante | Descrizione |
|---|---|---|
media: |
MEDIA_IDENTITY |
Top: qualsiasi tipo di dati (wildcard universale) |
media:void |
MEDIA_VOID |
Unit: il valore nullario (qui non scorre alcun dato) |
media:enc=utf-8 |
MEDIA_STRING |
Stringa UTF-8 |
media:integer;numeric |
MEDIA_INTEGER |
Intero |
media:numeric |
MEDIA_NUMBER |
Float |
media:bool;enc=utf-8 |
MEDIA_BOOLEAN |
Booleano |
media:record |
MEDIA_OBJECT |
Record/oggetto generico |
media:fmt=json;record |
MEDIA_JSON |
Oggetto JSON |
Array
| Media URN | Costante | Descrizione |
|---|---|---|
media:enc=utf-8;list |
MEDIA_STRING_LIST |
Array di stringhe |
media:integer;list;numeric |
MEDIA_INTEGER_LIST |
Array di interi |
media:list;numeric |
MEDIA_NUMBER_LIST |
Array di numeri |
media:bool;enc=utf-8;list |
MEDIA_BOOLEAN_LIST |
Array di booleani |
media:list;record |
MEDIA_OBJECT_LIST |
Lista di record opachi |
Medium e i loro formati
| Media URN | Costante | Descrizione |
|---|---|---|
media:image |
MEDIA_IMAGE |
Un’immagine in qualsiasi formato |
media:ext=png;image |
MEDIA_PNG |
Immagine PNG |
media:ext=jpeg;image |
MEDIA_JPEG |
Immagine JPEG |
media:audio |
MEDIA_AUDIO |
Audio in qualsiasi formato |
media:audio;ext=wav |
MEDIA_WAV |
Audio WAV |
media:video |
MEDIA_VIDEO |
Un video in qualsiasi contenitore |
media:ext=mp4;video |
MEDIA_MP4 |
Video MP4 |
media:document |
MEDIA_DOCUMENT |
Un documento in qualsiasi formato |
media:document;ext=pdf |
MEDIA_PDF |
Documento PDF |
Semantica della corrispondenza
La corrispondenza tra media URN segue la semantica dei tagged URN descritta in Dominio dei tagged URN.
Corrispondenza di pattern
Pattern: media:document
Istanza: media:document;ext=pdf
L'istanza ha tutti i tag richiesti dal pattern?
- Il pattern richiede: document=*
- L'istanza ha: document=*, ext=pdf
- document presente? Sì → CORRISPONDE ✓
Specificità
Più tag = più specifico:
spec(media:) = 0
spec(media:document) = 2 # document=* è must-have-any
spec(media:document;ext=pdf) = 6 # must-have-any (2) + valore esatto (4)
spec(media:document;ext=pdf;list) = 8
Conformità
media:document;ext=pdf ⪯ media:document (un pdf è un documento)
media:document ⪯ media: (un documento è conforme all'identità)
media:document;ext=pdf ⪯ media:image ✗ (non sulla stessa catena)
Specifiche di direzione nei cap URN
Quando sono usati come valori di in o out nei cap URN:
Quotatura
I media URN che contengono ; devono essere racchiusi tra virgolette:
cap:in="media:document;ext=pdf";extract;out="media:record"
Espansione dell’identità
in=* e out=* si espandono in media::
cap:in=*;convert;out=*
→ cap:in=media:;convert;out=media:
Dispatch
Per il dispatch (vedi Dispatch):
- Input: l’input della richiesta deve essere conforme all’input del candidato (controvariante)
- Output: l’output del candidato deve essere conforme all’output della richiesta (covariante)
Rilevamento del tipo
Metodi di supporto
let urn = MediaUrn::from_string("media:fmt=json;record")?;
urn.is_json() // true se e solo se get_tag("fmt") == Some("json")
urn.is_yaml() // true se e solo se get_tag("fmt") == Some("yaml")
urn.is_csv() // true se e solo se get_tag("fmt") == Some("csv")
urn.is_void() // true se e solo se è presente il tag marker `void` (tipo unità)
urn.is_top() // true se e solo se l'URN non ha alcun tag (tipo top)
I predicati di formato (is_json / is_yaml / is_csv) leggono l’asse
fmt=: ciascuno è semplicemente get_tag("fmt") == Some(<format>). Non esistono
is_text() né is_binary(). Tutto
è binario a livello di byte, quindi “testo contro binario” non è una vera
distinzione. Il testo è identificato dalla presenza del tag enc=:
urn.has_tag("enc") // true → questo valore è testo
urn.get_tag("enc") // Some("utf-8") → la codifica, se presente
Non esiste un metodo is_utf8; chi chiama esamina direttamente
get_tag("enc").
is_void e is_top sono i predicati che il classificatore
CapKind consulta. Insieme permettono a
qualsiasi chiamante di stabilire se un media URN è un tipo concreto, il wildcard o il tipo unità
senza analizzare stringhe.
Interrogazioni sui tag
urn.has_tag("enc") // true (testo)
urn.has_tag("fmt") // true (serializzato)
urn.has_tag("list") // false
urn.has_tag("record") // true
Aggiungere nuovi tipi
Quando si definisce un nuovo tipo di media:
- Stabilisci il formato del contenuto (
fmt=) e/o la codifica (enc=): come è serializzato questo valore, ed è testo? - Stabilisci struttura/cardinalità: scalare predefinito oppure
list, opaco predefinito oppurerecord - Aggiungi una costante se usato di frequente
- Documentalo nel catalogo dei media
Esempio: tipo personalizzato
// Un nuovo tipo per log strutturati (serializzati come JSON)
const MEDIA_LOG_ENTRY: &str = "media:log-entry;fmt=json;record";
// Serializzato come JSON, strutturato come record
Posizione nell’ordine parziale
I media URN formano un ordine parziale (ordine di specializzazione). media: è
l’unico top; media:void è una foglia, distinta da ogni tipo
concreto:
media: (top — qualsiasi A)
/ \
media:enc=utf-8 media:void (foglia — unit ())
/ \
media:integer;numeric media:fmt=json;record
|
media:fmt=json;list;record
Più tag = più in basso nell’ordine = più specifico. media:void porta
esattamente un tag (void) e quindi ha specificità 2 (un tag
must-have-any, più il prefisso); non è un raffinamento di alcun
tipo concreto.
Riepilogo
| Concetto | Definizione |
|---|---|
| Struttura | media:<type>[;tag=value]... |
| Top | media:: wildcard universale, massimo dell’ordine parziale, “qualsiasi A” |
| Unit | media:void: valore nullario, foglia dell’ordine parziale, “()” |
| Assi dei media | ext= (tipo di file), fmt= (serializzazione), enc= (codifica) |
| Marker semantici | numeric, visual/image, audio, video |
| Marker strutturali | list e record; scalare e opaco sono i valori predefiniti per assenza |
| Corrispondenza | Semantica dei tagged URN (tabella di verità) |
| Specificità | Somma dei punteggi dei singoli tag |
I media URN descrivono tipi di dati. Sono usati:
- Nelle specifiche
in/outdei cap URN (dove la scelta tramedia:,media:voide un tipo concreto determina il tipo della cap) - Come identificatori di argomenti
- Per la corrispondenza dei tipi nel dispatch