Some checks failed
joule-moq-web browser client / joule-moq-web · does this change touch it (push) Has been cancelled
joule-moq-web browser client / joule-moq-web · browser end-to-end (macos) (push) Has been cancelled
repository checks / lockfiles, advisories, tests in CI, workflow hygiene, spec and section references, public text (push) Has been cancelled
wai-app and Create / wai-app · does this change touch it (push) Has been cancelled
wai-app and Create / wai-app · tests, clippy, the line language's verifier (linux) (push) Has been cancelled
wai-app and Create / wai-app · Create, browser end-to-end (macos) (push) Has been cancelled
wai-fleet service / does this change touch it (push) Has been cancelled
wai-fleet service / service · linux (push) Has been cancelled
wai-fleet service / service · macos (push) Has been cancelled
WAI Studio / does this change touch it (push) Has been cancelled
WAI Studio / the catalogue's actions, the unit tests and the core · linux (push) Has been cancelled
WAI Studio / Studio in Chromium and Firefox · macos (push) Has been cancelled
WAI Studio / Studio in WebKit · linux (push) Has been cancelled
wai-audit collector and player integration / does this change touch it (push) Successful in 6s
WAI operation catalogue / does this change touch it (push) Successful in 5s
wai-key-proxy / does this change touch it (push) Successful in 6s
wai-ledger service / does this change touch it (push) Successful in 5s
wai-quantum for JavaScript / does this change touch it (push) Successful in 5s
wai-quantum studio and desktop / does this change touch it (push) Successful in 5s
wai-sink-android native sink library / does this change touch it (push) Successful in 5s
wai-sink-swift native sink package / does this change touch it (push) Successful in 6s
wai-quantum studio and desktop / desktop app · windows (push) Successful in 9m0s
wai-audit collector and player integration / collector · linux (push) Successful in 1m11s
wai-key-proxy / proxy · linux (push) Successful in 1m12s
wai-ledger service / service · linux (push) Successful in 2m24s
wai-quantum for JavaScript / javascript · linux (push) Successful in 3m17s
WAI operation catalogue / the catalogue and every door · linux (push) Successful in 5m9s
wai-quantum studio and desktop / desktop app · linux (push) Successful in 5m5s
wai-quantum studio and desktop / studio · browser (push) Successful in 9m15s
wai-audit collector and player integration / collector, player integration and the browser end to end · macos (push) Has been cancelled
wai-ledger service / service · macos (push) Has been cancelled
wai-quantum studio and desktop / desktop app · macos (push) Has been cancelled
wai-sink-android native sink library / the JNI layer and the platform-free half on the host JVM · linux-arm64 (push) Has been cancelled
wai-sink-android native sink library / every ABI, the AAR, and the instrumented tests in a headless emulator · macos (push) Has been cancelled
wai-sink-swift native sink package / libwai slices, desktop tests, simulator tests · macos (push) Has been cancelled
2291 lines
126 KiB
Rust
2291 lines
126 KiB
Rust
//! The registry as one table: every string SPEC §5 registers, with its kind, its
|
|
//! registration status, its media class, the section of SPEC that registers it,
|
|
//! the edition it carries and the date it was registered — and the named
|
|
//! identifiers and unregistered labels that look like capability strings but are
|
|
//! not capabilities.
|
|
//!
|
|
//! This module is unconditional (no feature gate), so every build of the crate
|
|
//! sees the same registry, and `wai registry export` writes the same files from
|
|
//! every build. The export ([`export_files`]) is the machine-readable registry:
|
|
//! `wai/registry/capabilities.json`, its JSON Schema, the generated vocabulary
|
|
//! `wai/vocab/v2.*`, and the generated table in `wai/REGISTRY.md`. A library test
|
|
//! holds each committed file byte-equal to what this module renders, so a change
|
|
//! here that is not exported fails, and so does a hand edit of an exported file.
|
|
//!
|
|
//! The policy the table implements is stated in `wai/REGISTRY.md`.
|
|
|
|
use super::*;
|
|
|
|
/// Whether a registered string's payload format is pinned (SPEC §5, *Candidate
|
|
/// capabilities*).
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
|
pub enum RegistrationStatus {
|
|
/// Registered with a pinned payload format (or, for a record or derivation, a
|
|
/// pinned definition): encoders may emit it and sinks may dispatch it.
|
|
Registered,
|
|
/// Registered, but no revision has pinned its payload format. An encoder MUST
|
|
/// NOT emit it, and a sink MUST treat it as unsupported (SPEC §5).
|
|
Candidate,
|
|
}
|
|
|
|
impl RegistrationStatus {
|
|
/// Every status, in declaration order. (A function, not an associated
|
|
/// constant, so the C header generator does not export it.)
|
|
pub const fn all() -> [Self; 2] {
|
|
[Self::Registered, Self::Candidate]
|
|
}
|
|
/// The label the export and `wai capabilities` use.
|
|
pub fn label(self) -> &'static str {
|
|
match self {
|
|
Self::Registered => "registered",
|
|
Self::Candidate => "candidate",
|
|
}
|
|
}
|
|
}
|
|
|
|
/// What a registered string names (SPEC §5, *Kinds of registered string*).
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
|
pub enum Kind {
|
|
/// A payload capability: the envelope's `capability` (or `fallback`, or a
|
|
/// `WAI2` rendition) names the codec its payload is decoded with.
|
|
Payload,
|
|
/// A companion-only capability ([`is_companion_only`]): its payload is applied
|
|
/// with a base rendition, never on its own.
|
|
Companion,
|
|
/// A refinement-only capability ([`is_refinement_only`]): its payload is applied,
|
|
/// in a declared order, to the output of the stage below it, bound to that
|
|
/// output's producer by content hash, never on its own
|
|
/// (`extensions/staged-delivery.md`).
|
|
Refinement,
|
|
/// A derivation operation of ISO/IEC 23001-16 (`wai.derive.*`): it acts on
|
|
/// samples another capability decoded and names no payload format.
|
|
Derivation,
|
|
/// A signed record a WAI tool emits and verifies (a receipt kind). It names
|
|
/// no payload format and is never an envelope's capability.
|
|
Record,
|
|
}
|
|
|
|
impl Kind {
|
|
/// Every kind, in declaration order.
|
|
pub const fn all() -> [Self; 5] {
|
|
[Self::Payload, Self::Companion, Self::Refinement, Self::Derivation, Self::Record]
|
|
}
|
|
/// The label the export uses.
|
|
pub fn label(self) -> &'static str {
|
|
match self {
|
|
Self::Payload => "payload",
|
|
Self::Companion => "companion",
|
|
Self::Refinement => "refinement",
|
|
Self::Derivation => "derivation",
|
|
Self::Record => "record",
|
|
}
|
|
}
|
|
}
|
|
|
|
/// The media class of a payload or companion capability: the value `wai wrap`
|
|
/// writes in a manifest's `media` field (SPEC §3: informational; the capability
|
|
/// is authoritative).
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
|
pub enum Media {
|
|
Image,
|
|
Audio,
|
|
Video,
|
|
Text,
|
|
/// Meshes, point clouds and Gaussian splats.
|
|
Volumetric,
|
|
Haptic,
|
|
/// Metadata applied with another payload (the HDR dynamic-metadata descriptors).
|
|
Metadata,
|
|
/// Worlds, feeds and avatars: content that consumes input.
|
|
Interactive,
|
|
/// A payload in none of the classes above.
|
|
Binary,
|
|
}
|
|
|
|
impl Media {
|
|
/// Every media class, in declaration order.
|
|
pub const fn all() -> [Self; 9] {
|
|
[
|
|
Self::Image, Self::Audio, Self::Video, Self::Text, Self::Volumetric,
|
|
Self::Haptic, Self::Metadata, Self::Interactive, Self::Binary,
|
|
]
|
|
}
|
|
/// The manifest value.
|
|
pub fn label(self) -> &'static str {
|
|
match self {
|
|
Self::Image => "image",
|
|
Self::Audio => "audio",
|
|
Self::Video => "video",
|
|
Self::Text => "text",
|
|
Self::Volumetric => "volumetric",
|
|
Self::Haptic => "haptic",
|
|
Self::Metadata => "metadata",
|
|
Self::Interactive => "interactive",
|
|
Self::Binary => "binary",
|
|
}
|
|
}
|
|
}
|
|
|
|
impl LicenseClass {
|
|
/// Every class, in declaration order.
|
|
pub const fn all() -> [Self; 4] {
|
|
[Self::RoyaltyFree, Self::PatentPool, Self::Proprietary, Self::NonCommercial]
|
|
}
|
|
/// The label SPEC §5 gives the class, which `wai capabilities` prints and the
|
|
/// codec glossary and the registry export record.
|
|
pub fn label(self) -> &'static str {
|
|
match self {
|
|
Self::RoyaltyFree => "royalty-free",
|
|
Self::PatentPool => "patent-pool",
|
|
Self::Proprietary => "proprietary",
|
|
Self::NonCommercial => "non-commercial",
|
|
}
|
|
}
|
|
}
|
|
|
|
impl FidelityTier {
|
|
/// Every tier, in declaration order.
|
|
pub const fn all() -> [Self; 3] {
|
|
[Self::Lossless, Self::Lossy, Self::Perceptual]
|
|
}
|
|
/// The label the export uses.
|
|
pub fn label(self) -> &'static str {
|
|
match self {
|
|
Self::Lossless => "lossless",
|
|
Self::Lossy => "lossy",
|
|
Self::Perceptual => "perceptual",
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ReplicateClass {
|
|
/// Every class, in declaration order.
|
|
pub const fn all() -> [Self; 8] {
|
|
[
|
|
Self::StandardDefined, Self::StandardTolerance, Self::StandardUnclassified,
|
|
Self::NeuralIntegerExact, Self::NeuralEntropyExact, Self::GenerativeDeterministic,
|
|
Self::NeuralFloat, Self::Behavioral,
|
|
]
|
|
}
|
|
}
|
|
|
|
/// The role labels `wai capabilities` prints and the export records for a
|
|
/// payload, companion or refinement capability.
|
|
pub const ROLE_LABELS: [&str; 4] = ["standalone", "companion", "enhancement", "refinement"];
|
|
|
|
/// How dispatch treats a payload, companion or refinement capability's payload:
|
|
/// standalone media, a companion applied with a base rendition, an enhancement layer
|
|
/// bound to exactly one base encode (SPEC §5, §7.1), or a refinement applied to the
|
|
/// output of the stage below it (SPEC §5, *Refinement capabilities*). `None` for any
|
|
/// other string.
|
|
pub fn capability_role(cap: &str) -> Option<&'static str> {
|
|
if !is_known_capability(cap) {
|
|
None
|
|
} else if is_refinement_only(cap) {
|
|
Some("refinement")
|
|
} else if is_enhancement_layer(cap) {
|
|
Some("enhancement")
|
|
} else if is_companion_only(cap) {
|
|
Some("companion")
|
|
} else {
|
|
Some("standalone")
|
|
}
|
|
}
|
|
|
|
/// The registered capabilities whose payload format no revision has pinned
|
|
/// (SPEC §5, *Candidate capabilities*).
|
|
const CANDIDATES: &[&str] = &[CAP_TENSOR_NNC, CAP_SPLAT_SOG, CAP_IMAGE_IEEE1857_11];
|
|
|
|
// ---- Records -----------------------------------------------------------------
|
|
|
|
/// The record kinds SPEC §5 registers. The quantum strings are copies of
|
|
/// `wai_quantum::quantum_ops::CAP_QUANTUM_{CALIBRATION,JOB}`; a test under the
|
|
/// `quantum_ops` feature holds them equal.
|
|
pub const CAP_ASSET_PROVENANCE: &str = "wai.asset.provenance";
|
|
pub const CAP_QUANTUM_CALIBRATION: &str = "wai.quantum.calibration";
|
|
pub const CAP_QUANTUM_JOB: &str = "wai.quantum.job";
|
|
pub const CAP_VIDEO_MANIFEST: &str = "wai.video.manifest";
|
|
pub const CAP_VIDEO_SSAI: &str = "wai.video.ssai";
|
|
pub const CAP_VIDEO_KEYS: &str = "wai.video.keys";
|
|
pub const CAP_VIDEO_PACKAGE: &str = "wai.video.package";
|
|
pub const CAP_VIDEO_CHANNEL: &str = "wai.video.channel";
|
|
pub const CAP_LIVE_EVENTS: &str = "wai.live.events";
|
|
pub const CAP_LIVE_ROOM: &str = "wai.live.room";
|
|
pub const CAP_CAPTURE_TAKE: &str = "wai.capture.take";
|
|
pub const CAP_LIVE_COMPOSE: &str = "wai.live.compose";
|
|
pub const CAP_LIVE_RECORDING: &str = "wai.live.recording";
|
|
pub const CAP_LIVE_METERING: &str = "wai.live.metering";
|
|
pub const CAP_LIVE_STEERING: &str = "wai.live.steering";
|
|
pub const CAP_LIVE_CONTRIBUTION: &str = "wai.live.contribution";
|
|
pub const CAP_TEXT_TIMED: &str = "wai.text.timed";
|
|
pub const CAP_LIVE_MODERATION: &str = "wai.live.moderation";
|
|
pub const CAP_LIVE_E2EE: &str = "wai.live.e2ee";
|
|
pub const CAP_LIVE_MESSAGE: &str = "wai.live.message";
|
|
pub const CAP_LIVE_CALL: &str = "wai.live.call";
|
|
pub const CAP_LIVE_WATERMARK: &str = "wai.live.watermark";
|
|
pub const CAP_LIVE_ADS: &str = "wai.live.ads";
|
|
pub const CAP_LIVE_AD_PRESENTATION: &str = "wai.live.ad_presentation";
|
|
pub const CAP_VIDEO_STITCHED_PRESENTATION: &str = "wai.video.stitched_presentation";
|
|
pub const CAP_VIDEO_LINEUP: &str = "wai.video.lineup";
|
|
pub const CAP_LIVE_COWATCH: &str = "wai.live.cowatch";
|
|
pub const CAP_LIVE_REMOTE: &str = "wai.live.remote";
|
|
pub const CAP_LIVE_WORLD: &str = "wai.live.world";
|
|
pub const CAP_LIVE_PROVENANCE: &str = "wai.live.provenance";
|
|
pub const CAP_EDGE_DERIVATION: &str = "wai.edge.derivation";
|
|
pub const CAP_MEDIA_SYNTHESIS: &str = "wai.media.synthesis";
|
|
pub const CAP_MEDIA_UPSCALE: &str = "wai.media.upscale";
|
|
pub const CAP_AI_USAGE: &str = "wai.ai.usage";
|
|
pub const CAP_MEDIA_CONTRIBUTION: &str = "wai.media.contribution";
|
|
pub const CAP_DELIVERY_SETTLEMENT: &str = "wai.delivery.settlement";
|
|
pub const CAP_DELIVERY_LEDGER: &str = "wai.delivery.ledger";
|
|
pub const CAP_DELIVERY_AUDIT: &str = "wai.delivery.audit";
|
|
pub const CAP_DELIVERY_FLEET: &str = "wai.delivery.fleet";
|
|
pub const CAP_ROUTE_RECORD: &str = "wai.route.record";
|
|
pub const CAP_DELIVERY_REVENUE_SHARE: &str = "wai.delivery.revenue_share";
|
|
pub const CAP_DELIVERY_OPPORTUNITY: &str = "wai.delivery.opportunity";
|
|
pub const CAP_MEDIA_TAKEDOWN: &str = "wai.media.takedown";
|
|
pub const CAP_LIVE_COPERFORMANCE: &str = "wai.live.coperformance";
|
|
pub const CAP_MEDIA_INFLUENCE: &str = "wai.media.influence";
|
|
pub const CAP_MEDIA_DIRECTION: &str = "wai.media.direction";
|
|
pub const CAP_BEARER_RECEIPTS: &str = "wai.bearer.receipts";
|
|
pub const CAP_BEARER_CAROUSEL: &str = "wai.bearer.carousel";
|
|
pub const CAP_DELIVERY_HOLDINGS: &str = "wai.delivery.holdings";
|
|
pub const CAP_DELIVERY_TIMELINESS: &str = "wai.delivery.timeliness";
|
|
pub const CAP_DELIVERY_RUNG_PRICE: &str = "wai.delivery.rung_price";
|
|
pub const CAP_DELIVERY_CACHE: &str = "wai.delivery.cache";
|
|
pub const CAP_DELIVERY_IMPRESSIONS: &str = "wai.delivery.impressions";
|
|
pub const CAP_ACCESS_SERVICES: &str = "wai.access.services";
|
|
pub const CAP_AGE_ASSURANCE: &str = "wai.age.assurance";
|
|
pub const CAP_MEDIA_EXPLORATION: &str = "wai.media.exploration";
|
|
pub const CAP_VIDEO_ENCODE: &str = "wai.video.encode";
|
|
pub const CAP_TELEMETRY_AGGREGATE: &str = "wai.telemetry.aggregate";
|
|
pub const CAP_MEDIA_TONEMAP: &str = "wai.media.tonemap";
|
|
pub const CAP_MEDIA_ROBUSTNESS: &str = "wai.media.robustness";
|
|
pub const CAP_SPLAT_EXACT: &str = "wai.splat.exact";
|
|
pub const CAP_LIVE_TERMINATION: &str = "wai.live.termination";
|
|
pub const CAP_SINK_ENERGY: &str = "wai.sink.energy";
|
|
pub const CAP_LIVE_INJECTION: &str = "wai.live.injection";
|
|
|
|
/// One row per string SPEC §5 registers that is a payload, companion or record:
|
|
/// `(string, SPEC section, edition, registered)`.
|
|
///
|
|
/// - The section is the heading of SPEC §5 under which the string is registered.
|
|
/// - `edition` is the designation of the edition the registration names, or
|
|
/// `None`: then the string carries the edition of its named standard current on
|
|
/// the date it was registered, and no later edition or amendment (SPEC §8,
|
|
/// *Editions*).
|
|
/// - `registered` is the date of the first commit of this repository that
|
|
/// registers the string. The specification entered this repository on
|
|
/// 2026-06-12; a string registered before then carries that date.
|
|
const ROWS: &[(&str, &str, Option<&str>, &str)] = &[
|
|
(CAP_IMAGE_PNG, S_FLOOR, None, "2026-06-12"),
|
|
(CAP_AUDIO_FLAC, S_FLOOR, None, "2026-06-12"),
|
|
(CAP_TEXT_ZSTD, S_FLOOR, None, "2026-06-12"),
|
|
(CAP_IMAGE_JXL, S_RECOMMENDED, None, "2026-06-12"),
|
|
(CAP_IMAGE_AVIF, S_RECOMMENDED, None, "2026-06-12"),
|
|
(CAP_IMAGE_JPEG, S_RECOMMENDED, None, "2026-06-12"),
|
|
(CAP_AUDIO_OPUS, S_RECOMMENDED, None, "2026-06-12"),
|
|
(CAP_VIDEO_AV1, S_RECOMMENDED, None, "2026-06-12"),
|
|
(CAP_VIDEO_AV1_LOSSLESS, S_RECOMMENDED, None, "2026-06-12"),
|
|
(CAP_TEXT_XZ, S_RECOMMENDED, None, "2026-06-12"),
|
|
(CAP_NEURAL_ENCODEC32, S_NEURAL, None, "2026-06-12"),
|
|
(CAP_NEURAL_DAC, S_NEURAL, None, "2026-06-12"),
|
|
(CAP_NEURAL_MIMI, S_NEURAL, None, "2026-06-12"),
|
|
(CAP_NEURAL_WAVTOKENIZER, S_NEURAL, None, "2026-06-12"),
|
|
(CAP_NEURAL_SNAC, S_NEURAL, None, "2026-06-13"),
|
|
(CAP_NEURAL_BMSHJ2018, S_NEURAL, None, "2026-06-12"),
|
|
(CAP_NEURAL_MBT2018_MEAN, S_NEURAL, None, "2026-06-13"),
|
|
(CAP_NEURAL_INT_SYNTH, S_NEURAL, None, "2026-06-13"),
|
|
(CAP_NEURAL_INT_HYPER, S_NEURAL, None, "2026-06-24"),
|
|
(CAP_NEURAL_INT_MLICPP, S_NEURAL, None, "2026-09-30"),
|
|
(CAP_IMAGE_JPEGAI, S_NEURAL, Some("ISO/IEC 6048-1:2025"), "2026-06-13"),
|
|
(CAP_IMAGE_IEEE1857_11, S_NEURAL, Some("IEEE 1857.11-2024"), "2026-10-22"),
|
|
(CAP_GENERATE_SPECTRAL, S_NEURAL, None, "2026-06-25"),
|
|
(CAP_NEURAL_ELIC, S_NEURAL, None, "2026-06-13"),
|
|
(CAP_NEURAL_MLICPP, S_NEURAL, None, "2026-06-13"),
|
|
(CAP_NEURAL_MLICV2, S_NEURAL, None, "2026-06-13"),
|
|
(CAP_NEURAL_CMIC, S_NEURAL, None, "2026-06-13"),
|
|
(CAP_NEURAL_GLC, S_NEURAL, None, "2026-06-12"),
|
|
(CAP_SEMANTIC_CLIP, S_NEURAL, None, "2026-06-13"),
|
|
(CAP_SEMANTIC_PERCO2, S_NEURAL, None, "2026-06-13"),
|
|
(CAP_NEURAL_VIDEO_BMSHJ2018, S_NEURAL, None, "2026-06-12"),
|
|
(CAP_NEURAL_DCVC_RT, S_NEURAL, None, "2026-06-12"),
|
|
(CAP_NEURAL_DCVC_FM, S_NEURAL, None, "2026-06-13"),
|
|
(CAP_VIDEO_INT_MOTION, S_NEURAL, None, "2026-06-27"),
|
|
(CAP_VIDEO_INT_HYPER, S_NEURAL, None, "2026-06-27"),
|
|
(CAP_VIDEO_MANIFEST, S_NEURAL, None, "2026-09-03"),
|
|
(CAP_VIDEO_SSAI, S_NEURAL, None, "2026-09-03"),
|
|
(CAP_VIDEO_KEYS, S_NEURAL, None, "2026-09-03"),
|
|
(CAP_VIDEO_PACKAGE, S_NEURAL, None, "2026-09-03"),
|
|
(CAP_VIDEO_CHANNEL, S_NEURAL, None, "2026-09-03"),
|
|
(CAP_PRIOR_NNC, S_PRIOR, Some("ISO/IEC 15938-17:2024"), "2026-09-28"),
|
|
(CAP_PRIOR_SET, S_PRIOR, None, "2026-09-30"),
|
|
(CAP_PRIOR_SAFETENSORS, S_PRIOR, None, "2026-10-22"),
|
|
(CAP_PRIOR_GGUF, S_PRIOR, Some("GGUF version 3"), "2026-10-22"),
|
|
(CAP_PRIOR_SEALED, S_PRIOR, None, "2026-11-04"),
|
|
(CAP_PRIOR_TREE, S_PRIOR, None, "2026-11-04"),
|
|
(CAP_TENSOR_NNC, S_PRIOR, None, "2026-09-28"),
|
|
(CAP_EDGE_DERIVATION, S_PRIOR, None, "2026-10-21"),
|
|
(CAP_WORLD_SCENE, S_INTERACTIVE, None, "2026-06-13"),
|
|
(CAP_WORLD_REPLAY, S_INTERACTIVE, None, "2026-06-13"),
|
|
(CAP_WORLD_LIVE, S_INTERACTIVE, None, "2026-06-13"),
|
|
(CAP_WORLD_MODEL, S_INTERACTIVE, None, "2026-06-27"),
|
|
(CAP_MESH_GLB, S_INTERACTIVE, None, "2026-06-13"),
|
|
(CAP_SPLAT_SPZ, S_INTERACTIVE, None, "2026-06-13"),
|
|
(CAP_AUDIO_SCENE, S_INTERACTIVE, None, "2026-06-13"),
|
|
(CAP_AUDIO_SCORE, S_INTERACTIVE, None, "2026-06-14"),
|
|
(CAP_AUDIO_INT_CODEC, S_INTERACTIVE, None, "2026-06-27"),
|
|
(CAP_HAPTIC_SIGNAL, S_INTERACTIVE, None, "2026-06-13"),
|
|
(CAP_FEED_STATE, S_INTERACTIVE, None, "2026-06-13"),
|
|
(CAP_AVATAR_POSE, S_INTERACTIVE, None, "2026-06-13"),
|
|
(CAP_AVATAR_FACE, S_INTERACTIVE, None, "2026-10-22"),
|
|
(CAP_SPLAT_4D, S_INTERACTIVE, None, "2026-06-13"),
|
|
(CAP_SPLAT_INT_CODEC, S_INTERACTIVE, None, "2026-06-28"),
|
|
(CAP_FILM_LINEAR, S_INTERACTIVE, None, "2026-06-16"),
|
|
(CAP_FILM_REEL, S_INTERACTIVE, None, "2026-06-17"),
|
|
(CAP_TERNARY_TT, S_INTERACTIVE, None, "2026-07-30"),
|
|
(CAP_QUANTUM_CIRCUIT, S_INTERACTIVE, None, "2026-07-25"),
|
|
(CAP_QUANTUM_CIRCUIT2, S_INTERACTIVE, None, "2026-10-09"),
|
|
(CAP_ASSET_PROVENANCE, S_INTERACTIVE, None, "2026-06-13"),
|
|
(CAP_QUANTUM_CALIBRATION, S_INTERACTIVE, None, "2026-08-01"),
|
|
(CAP_QUANTUM_JOB, S_INTERACTIVE, None, "2026-08-01"),
|
|
(CAP_LIVE_EVENTS, S_INTERACTIVE, None, "2026-10-16"),
|
|
(CAP_LIVE_ROOM, S_INTERACTIVE, None, "2026-10-16"),
|
|
(CAP_CAPTURE_TAKE, S_INTERACTIVE, None, "2026-10-17"),
|
|
(CAP_LIVE_COMPOSE, S_INTERACTIVE, None, "2026-10-17"),
|
|
(CAP_LIVE_RECORDING, S_INTERACTIVE, None, "2026-10-17"),
|
|
(CAP_LIVE_METERING, S_INTERACTIVE, None, "2026-10-18"),
|
|
(CAP_LIVE_STEERING, S_INTERACTIVE, None, "2026-10-18"),
|
|
(CAP_LIVE_CONTRIBUTION, S_INTERACTIVE, None, "2026-10-26"),
|
|
(CAP_TEXT_TIMED, S_INTERACTIVE, None, "2026-10-17"),
|
|
(CAP_LIVE_MODERATION, S_INTERACTIVE, None, "2026-10-19"),
|
|
(CAP_LIVE_E2EE, S_INTERACTIVE, None, "2026-10-19"),
|
|
(CAP_LIVE_MESSAGE, S_INTERACTIVE, None, "2026-10-26"),
|
|
(CAP_LIVE_CALL, S_INTERACTIVE, None, "2026-10-26"),
|
|
(CAP_LIVE_WATERMARK, S_INTERACTIVE, None, "2026-10-20"),
|
|
(CAP_LIVE_ADS, S_INTERACTIVE, None, "2026-10-20"),
|
|
(CAP_LIVE_AD_PRESENTATION, S_INTERACTIVE, None, "2026-10-21"),
|
|
(CAP_VIDEO_STITCHED_PRESENTATION, S_INTERACTIVE, None, "2026-10-25"),
|
|
(CAP_VIDEO_LINEUP, S_INTERACTIVE, None, "2026-10-29"),
|
|
(CAP_LIVE_COWATCH, S_INTERACTIVE, None, "2026-10-22"),
|
|
(CAP_LIVE_REMOTE, S_INTERACTIVE, None, "2026-10-25"),
|
|
(CAP_LIVE_PROVENANCE, S_INTERACTIVE, None, "2026-10-21"),
|
|
(CAP_MEDIA_SYNTHESIS, S_INTERACTIVE, None, "2026-10-21"),
|
|
(CAP_MEDIA_UPSCALE, S_INTERACTIVE, None, "2026-10-21"),
|
|
(CAP_AI_USAGE, S_INTERACTIVE, None, "2026-10-21"),
|
|
(CAP_MEDIA_CONTRIBUTION, S_INTERACTIVE, None, "2026-10-21"),
|
|
(CAP_DELIVERY_SETTLEMENT, S_INTERACTIVE, None, "2026-10-21"),
|
|
(CAP_DELIVERY_LEDGER, S_INTERACTIVE, None, "2026-10-25"),
|
|
(CAP_DELIVERY_AUDIT, S_INTERACTIVE, None, "2026-10-25"),
|
|
(CAP_DELIVERY_FLEET, S_INTERACTIVE, None, "2026-10-27"),
|
|
(CAP_ROUTE_RECORD, S_INTERACTIVE, None, "2026-10-29"),
|
|
(CAP_DELIVERY_REVENUE_SHARE, S_INTERACTIVE, None, "2026-10-29"),
|
|
(CAP_DELIVERY_OPPORTUNITY, S_INTERACTIVE, None, "2026-10-29"),
|
|
(CAP_MEDIA_TAKEDOWN, S_INTERACTIVE, None, "2026-10-21"),
|
|
(CAP_LIVE_COPERFORMANCE, S_INTERACTIVE, None, "2026-10-21"),
|
|
(CAP_MEDIA_INFLUENCE, S_INTERACTIVE, None, "2026-10-21"),
|
|
(CAP_MEDIA_DIRECTION, S_INTERACTIVE, None, "2026-10-21"),
|
|
(CAP_BEARER_RECEIPTS, S_INTERACTIVE, None, "2026-10-21"),
|
|
(CAP_BEARER_CAROUSEL, S_INTERACTIVE, None, "2026-11-02"),
|
|
(CAP_DELIVERY_HOLDINGS, S_INTERACTIVE, None, "2026-11-03"),
|
|
(CAP_DELIVERY_TIMELINESS, S_INTERACTIVE, None, "2026-11-03"),
|
|
(CAP_DELIVERY_RUNG_PRICE, S_INTERACTIVE, None, "2026-11-03"),
|
|
(CAP_DELIVERY_CACHE, S_INTERACTIVE, None, "2026-11-03"),
|
|
(CAP_DELIVERY_IMPRESSIONS, S_INTERACTIVE, None, "2026-11-03"),
|
|
(CAP_ACCESS_SERVICES, S_INTERACTIVE, None, "2026-10-21"),
|
|
(CAP_AGE_ASSURANCE, S_INTERACTIVE, None, "2026-10-21"),
|
|
(CAP_MEDIA_EXPLORATION, S_INTERACTIVE, None, "2026-10-21"),
|
|
(CAP_VIDEO_ENCODE, S_BROADCAST, None, "2026-10-26"),
|
|
(CAP_TELEMETRY_AGGREGATE, S_INTERACTIVE, None, "2026-10-22"),
|
|
(CAP_MEDIA_ROBUSTNESS, S_INTERACTIVE, None, "2026-10-22"),
|
|
(CAP_SPLAT_EXACT, S_INTERACTIVE, None, "2026-10-22"),
|
|
(CAP_LIVE_TERMINATION, S_INTERACTIVE, None, "2026-10-22"),
|
|
(CAP_SINK_ENERGY, S_INTERACTIVE, None, "2026-10-22"),
|
|
(CAP_LIVE_INJECTION, S_INTERACTIVE, None, "2026-10-25"),
|
|
(CAP_LIVE_WORLD, S_INTERACTIVE, None, "2026-10-26"),
|
|
(CAP_AUDIO_IAMF, S_IMMERSIVE, None, "2026-06-17"),
|
|
(CAP_AUDIO_AC4, S_IMMERSIVE, None, "2026-06-17"),
|
|
(CAP_AUDIO_IVAS, S_IMMERSIVE, None, "2026-06-17"),
|
|
(CAP_IMAGE_JP2, S_IMMERSIVE, None, "2026-06-17"),
|
|
(CAP_VIDEO_J2K, S_IMMERSIVE, None, "2026-06-17"),
|
|
(CAP_MESH_DRACO, S_IMMERSIVE, None, "2026-06-17"),
|
|
(CAP_PC_GPCC, S_IMMERSIVE, None, "2026-06-17"),
|
|
(CAP_PC_VPCC, S_IMMERSIVE, None, "2026-06-17"),
|
|
(CAP_SPLAT_SOG, S_IMMERSIVE, None, "2026-06-17"),
|
|
(CAP_HAPTIC_MIHS, S_IMMERSIVE, Some("ISO/IEC 23090-31:2025"), "2026-06-17"),
|
|
(CAP_META_HDR10PLUS, S_IMMERSIVE, None, "2026-06-17"),
|
|
(CAP_META_DOVI, S_IMMERSIVE, None, "2026-06-17"),
|
|
(CAP_META_GAINMAP, S_IMMERSIVE, Some("ISO 21496-1:2025"), "2026-10-22"),
|
|
(CAP_META_ST2094_50, S_IMMERSIVE, Some("SMPTE ST 2094-50:2026-08"), "2026-10-22"),
|
|
(CAP_MEDIA_TONEMAP, S_IMMERSIVE, None, "2026-10-22"),
|
|
(CAP_IMAGE_JXS, S_IMMERSIVE, None, "2026-10-22"),
|
|
(CAP_VIDEO_JXS, S_IMMERSIVE, None, "2026-10-22"),
|
|
(CAP_META_PROJECTION, S_IMMERSIVE, None, "2026-10-22"),
|
|
(CAP_VIDEO_AV2, S_BROADCAST, Some("AV2 Bitstream & Decoding Process Specification v1.0.0 (2026-05-28)"), "2026-09-28"),
|
|
(CAP_VIDEO_VVC, S_BROADCAST, None, "2026-09-28"),
|
|
(CAP_VIDEO_HEVC, S_BROADCAST, None, "2026-09-28"),
|
|
(CAP_VIDEO_AVC, S_BROADCAST, None, "2026-09-28"),
|
|
(CAP_VIDEO_VP9, S_BROADCAST, None, "2026-09-28"),
|
|
(CAP_VIDEO_EVC, S_BROADCAST, None, "2026-09-28"),
|
|
(CAP_VIDEO_EVC_BASELINE, S_BROADCAST, None, "2026-09-28"),
|
|
(CAP_VIDEO_AVS3, S_BROADCAST, Some("T/AI 109.2-2021"), "2026-09-28"),
|
|
(CAP_VIDEO_LCEVC, S_BROADCAST, None, "2026-09-28"),
|
|
(CAP_AUDIO_MPEGH, S_BROADCAST, None, "2026-09-28"),
|
|
(CAP_AUDIO_AVS3, S_BROADCAST, Some("T/AI 109.3-2023"), "2026-09-28"),
|
|
(CAP_AUDIO_AAC, S_BROADCAST, None, "2026-09-28"),
|
|
(CAP_VIDEO_VP8, S_BROADCAST, None, "2026-10-18"),
|
|
(CAP_AUDIO_OPUS_PACKET, S_BROADCAST, None, "2026-10-18"),
|
|
(CAP_AUDIO_OPUS_DRED, S_BROADCAST, Some("draft-ietf-mlcodec-opus-dred-07"), "2026-10-22"),
|
|
(CAP_AUDIO_OPUS_DRED_INT, S_BROADCAST, Some("draft-ietf-mlcodec-opus-dred-07"), "2026-10-22"),
|
|
(CAP_VIDEO_MVHEVC, S_BROADCAST, None, "2026-10-22"),
|
|
(CAP_IMAGE_INT_REFINE, S_REFINEMENT, None, "2026-10-01"),
|
|
(CAP_VIDEO_INT_REFINE, S_REFINEMENT, None, "2026-10-01"),
|
|
(CAP_AUDIO_INT_REFINE, S_REFINEMENT, None, "2026-10-01"),
|
|
(CAP_SPLAT_INT_REFINE, S_REFINEMENT, None, "2026-10-01"),
|
|
];
|
|
|
|
const S_FLOOR: &str = "§5 Mandatory floor";
|
|
const S_RECOMMENDED: &str = "§5 Recommended modern set";
|
|
const S_NEURAL: &str = "§5 Neural capabilities";
|
|
const S_PRIOR: &str = "§5 Prior artifacts, general tensors and derivation operations";
|
|
const S_INTERACTIVE: &str = "§5 Interactive, temporal & computed content";
|
|
const S_IMMERSIVE: &str = "§5 Immersive audio, cinema, volumetric, haptics, HDR";
|
|
const S_BROADCAST: &str = "§5 Broadcast and streaming codecs";
|
|
const S_REFINEMENT: &str = "§5 Refinement capabilities (staged delivery)";
|
|
|
|
/// The date the derivation operations were registered.
|
|
const DERIVATIONS_REGISTERED: &str = "2026-09-28";
|
|
|
|
/// The record kinds SPEC §5 registers (see [`Kind::Record`]).
|
|
const RECORDS: &[&str] = &[
|
|
CAP_ASSET_PROVENANCE, CAP_QUANTUM_CALIBRATION, CAP_QUANTUM_JOB,
|
|
CAP_VIDEO_MANIFEST, CAP_VIDEO_SSAI, CAP_VIDEO_KEYS, CAP_VIDEO_PACKAGE, CAP_VIDEO_CHANNEL,
|
|
CAP_LIVE_EVENTS, CAP_LIVE_ROOM, CAP_CAPTURE_TAKE, CAP_LIVE_COMPOSE, CAP_LIVE_RECORDING,
|
|
CAP_LIVE_METERING, CAP_LIVE_STEERING, CAP_LIVE_CONTRIBUTION, CAP_TEXT_TIMED, CAP_LIVE_MODERATION, CAP_LIVE_E2EE,
|
|
CAP_LIVE_MESSAGE,
|
|
CAP_LIVE_CALL,
|
|
CAP_LIVE_WATERMARK,
|
|
CAP_LIVE_ADS,
|
|
CAP_LIVE_AD_PRESENTATION,
|
|
CAP_VIDEO_STITCHED_PRESENTATION,
|
|
CAP_VIDEO_LINEUP,
|
|
CAP_LIVE_COWATCH,
|
|
CAP_LIVE_REMOTE,
|
|
CAP_LIVE_PROVENANCE,
|
|
CAP_EDGE_DERIVATION,
|
|
CAP_MEDIA_SYNTHESIS,
|
|
CAP_MEDIA_UPSCALE,
|
|
CAP_AI_USAGE,
|
|
CAP_MEDIA_CONTRIBUTION,
|
|
CAP_DELIVERY_SETTLEMENT,
|
|
CAP_DELIVERY_LEDGER,
|
|
CAP_DELIVERY_AUDIT,
|
|
CAP_DELIVERY_FLEET,
|
|
CAP_ROUTE_RECORD,
|
|
CAP_DELIVERY_REVENUE_SHARE,
|
|
CAP_DELIVERY_OPPORTUNITY,
|
|
CAP_MEDIA_TAKEDOWN,
|
|
CAP_LIVE_COPERFORMANCE,
|
|
CAP_MEDIA_INFLUENCE,
|
|
CAP_MEDIA_DIRECTION,
|
|
CAP_BEARER_RECEIPTS,
|
|
CAP_BEARER_CAROUSEL,
|
|
CAP_DELIVERY_HOLDINGS,
|
|
CAP_DELIVERY_TIMELINESS,
|
|
CAP_DELIVERY_RUNG_PRICE,
|
|
CAP_DELIVERY_CACHE,
|
|
CAP_DELIVERY_IMPRESSIONS,
|
|
CAP_ACCESS_SERVICES,
|
|
CAP_AGE_ASSURANCE,
|
|
CAP_MEDIA_EXPLORATION,
|
|
CAP_VIDEO_ENCODE,
|
|
CAP_TELEMETRY_AGGREGATE,
|
|
CAP_MEDIA_TONEMAP,
|
|
CAP_MEDIA_ROBUSTNESS,
|
|
CAP_SPLAT_EXACT,
|
|
CAP_LIVE_TERMINATION,
|
|
CAP_SINK_ENERGY,
|
|
CAP_LIVE_INJECTION,
|
|
CAP_LIVE_WORLD,
|
|
];
|
|
|
|
/// A named identifier SPEC uses that has the shape of a capability string but is
|
|
/// not a capability: it names a part of a capability's definition.
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
pub struct Identifier {
|
|
pub identifier: &'static str,
|
|
pub spec_section: &'static str,
|
|
pub meaning: &'static str,
|
|
}
|
|
|
|
/// Every [`Identifier`] SPEC uses.
|
|
pub const IDENTIFIERS: &[Identifier] = &[
|
|
Identifier {
|
|
identifier: "wai.det.amp64",
|
|
spec_section: S_INTERACTIVE,
|
|
meaning: "the complex fixed-point arithmetic of wai.quantum.circuit2: re and im each an i64 at scale 2^frac, products exact then rounded half up, sums exact (quantum-sim §2.1, §3.0)",
|
|
},
|
|
Identifier {
|
|
identifier: "wai.det.fixed64",
|
|
spec_section: S_INTERACTIVE,
|
|
meaning: "the fixed-point arithmetic floor the deterministic *-equivalence criteria are computed in (Q32.32, interactive-worlds §6.2); inside a wai.quantum.circuit contract it names the quantum-sim §3.0 arithmetic at frac 30, products rounded half up",
|
|
},
|
|
Identifier {
|
|
identifier: "wai.world.sim.feed0",
|
|
spec_section: S_INTERACTIVE,
|
|
meaning: "the identity simulation step of wai.feed.state",
|
|
},
|
|
Identifier {
|
|
identifier: "wai.world.sim.skeletal0",
|
|
spec_section: S_INTERACTIVE,
|
|
meaning: "the skeletal-pose simulation step of wai.avatar.pose",
|
|
},
|
|
];
|
|
|
|
/// What a [`WireIdentifier`] names.
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
|
pub enum WireKind {
|
|
/// A media type.
|
|
MediaType,
|
|
/// The prefix of a `codecs` element.
|
|
CodecsPrefix,
|
|
/// An ISOBMFF four-character code.
|
|
FourCc,
|
|
/// The magic number at the start of a binary format.
|
|
Magic,
|
|
/// An HLS `EXT-X-SESSION-DATA` `DATA-ID`.
|
|
DataId,
|
|
/// A URI scheme identifier (a DASH `schemeIdUri`).
|
|
Scheme,
|
|
/// A path suffix or a path segment a resource is named by.
|
|
Path,
|
|
/// A path under `/.well-known/` (RFC 8615).
|
|
WellKnown,
|
|
/// A playlist tag.
|
|
PlaylistTag,
|
|
/// A playlist attribute, or a value a WAI binding gives one (an `EXT-X-DATERANGE`
|
|
/// `CLASS`).
|
|
PlaylistAttribute,
|
|
/// The `kind` member of a JSON document.
|
|
DocumentKind,
|
|
/// A MoQ catalog value, catalog field or object property.
|
|
Catalog,
|
|
/// A MOQT Setup Option.
|
|
SetupOption,
|
|
/// An HTTP field name.
|
|
HttpHeader,
|
|
/// A member of a WebCodecs `VideoFrameMetadata` dictionary.
|
|
FrameMetadata,
|
|
/// The name of a glTF 2.0 extension (ISO/IEC 12113:2022): a key of an `extensions`
|
|
/// object, listed in `extensionsUsed`.
|
|
GltfExtension,
|
|
/// A custom key of a CMCD (CTA-5004-B) or CMSD (CTA-5006) report.
|
|
TelemetryKey,
|
|
/// A report extension type of the Distributed Aggregation Protocol
|
|
/// (`draft-ietf-ppm-dap-20` §4.4.2, its registry §9.2.4).
|
|
DapReportExtension,
|
|
}
|
|
|
|
impl WireKind {
|
|
/// Every kind, in declaration order.
|
|
pub const fn all() -> [Self; 18] {
|
|
[
|
|
Self::MediaType, Self::CodecsPrefix, Self::FourCc, Self::Magic, Self::DataId,
|
|
Self::Scheme, Self::Path, Self::WellKnown, Self::PlaylistTag,
|
|
Self::PlaylistAttribute, Self::DocumentKind, Self::Catalog, Self::SetupOption,
|
|
Self::HttpHeader, Self::FrameMetadata, Self::GltfExtension, Self::TelemetryKey,
|
|
Self::DapReportExtension,
|
|
]
|
|
}
|
|
/// The label the export uses.
|
|
pub fn label(self) -> &'static str {
|
|
match self {
|
|
Self::MediaType => "media-type",
|
|
Self::CodecsPrefix => "codecs-prefix",
|
|
Self::FourCc => "fourcc",
|
|
Self::Magic => "magic",
|
|
Self::DataId => "data-id",
|
|
Self::Scheme => "scheme",
|
|
Self::Path => "path",
|
|
Self::WellKnown => "well-known",
|
|
Self::PlaylistTag => "playlist-tag",
|
|
Self::PlaylistAttribute => "playlist-attribute",
|
|
Self::DocumentKind => "document-kind",
|
|
Self::Catalog => "catalog",
|
|
Self::SetupOption => "setup-option",
|
|
Self::HttpHeader => "http-header",
|
|
Self::FrameMetadata => "frame-metadata",
|
|
Self::GltfExtension => "gltf-extension",
|
|
Self::TelemetryKey => "telemetry-key",
|
|
Self::DapReportExtension => "dap-report-extension",
|
|
}
|
|
}
|
|
}
|
|
|
|
/// How settled a [`WireIdentifier`] is.
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
|
pub enum WireStatus {
|
|
/// Defined by its document, and used as defined.
|
|
Defined,
|
|
/// Defined by its document for test material only, until a registration
|
|
/// authority registers it.
|
|
Provisional,
|
|
/// Proposed for registration; its document says it is not registered.
|
|
Proposed,
|
|
}
|
|
|
|
impl WireStatus {
|
|
/// Every status, in declaration order.
|
|
pub const fn all() -> [Self; 3] {
|
|
[Self::Defined, Self::Provisional, Self::Proposed]
|
|
}
|
|
/// The label the export uses.
|
|
pub fn label(self) -> &'static str {
|
|
match self {
|
|
Self::Defined => "defined",
|
|
Self::Provisional => "provisional",
|
|
Self::Proposed => "proposed",
|
|
}
|
|
}
|
|
}
|
|
|
|
/// A name a WAI text puts on the wire outside a manifest: a media type, a `codecs`
|
|
/// prefix, a magic number, a path, a playlist tag or attribute, a document kind, a
|
|
/// catalog field. `document` is the text that defines it, relative to `wai/`, and
|
|
/// `section` the section there (`§N` or `Appendix X`).
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
pub struct WireIdentifier {
|
|
pub name: &'static str,
|
|
pub kind: WireKind,
|
|
pub document: &'static str,
|
|
pub section: &'static str,
|
|
pub status: WireStatus,
|
|
}
|
|
|
|
const HTTP_DELIVERY: &str = "extensions/http-delivery.md";
|
|
const MOQ_FORMAT: &str = "extensions/moq-streaming-format.md";
|
|
const JWP_RECEIPTS: &str = "extensions/jwp-receipts.md";
|
|
const HOLDINGS: &str = "extensions/holdings.md";
|
|
const PACKAGING: &str = "extensions/packaging.md";
|
|
const LIVE_EVENTS: &str = "extensions/live-events.md";
|
|
const LIVE_ROOMS: &str = "extensions/live-rooms.md";
|
|
const CAPTURE_BINDING: &str = "extensions/capture-binding.md";
|
|
const LIVE_COMPOSE: &str = "extensions/live-compose.md";
|
|
const LIVE_RECORDING: &str = "extensions/live-recording.md";
|
|
const TIMED_TEXT: &str = "extensions/timed-text.md";
|
|
const LIVE_METERING: &str = "extensions/live-metering.md";
|
|
const ENERGY_STEERING: &str = "extensions/energy-steering.md";
|
|
const LIVE_CONTRIBUTION: &str = "extensions/live-contribution.md";
|
|
const LIVE_MODERATION: &str = "extensions/live-moderation.md";
|
|
const CONFIDENTIALITY: &str = "extensions/confidentiality.md";
|
|
const LIVE_MESSAGING: &str = "extensions/live-messaging.md";
|
|
const FORENSIC_WATERMARK: &str = "extensions/forensic-watermark.md";
|
|
const AI_USAGE: &str = "extensions/ai-usage.md";
|
|
const CO_PERFORMANCE: &str = "extensions/co-performance.md";
|
|
const LIVE_ADS: &str = "extensions/live-ads.md";
|
|
const AD_PRESENTATION: &str = "extensions/ad-presentation.md";
|
|
const STITCHED_PRESENTATION: &str = "extensions/stitched-presentation.md";
|
|
const CHANNEL_LINEUP: &str = "extensions/channel-lineup.md";
|
|
const CO_WATCH: &str = "extensions/co-watch.md";
|
|
const REMOTE_DESKTOP: &str = "extensions/remote-desktop.md";
|
|
const LIVE_PROVENANCE: &str = "extensions/live-provenance.md";
|
|
const DERIVING_EDGE: &str = "extensions/deriving-edge.md";
|
|
const SYNTHESIS: &str = "extensions/synthesis.md";
|
|
const CONTRIBUTION: &str = "extensions/contribution.md";
|
|
const SETTLEMENT: &str = "extensions/settlement.md";
|
|
const LEDGER: &str = "extensions/receipt-ledger.md";
|
|
const STREAM_AUDIT: &str = "extensions/stream-audit.md";
|
|
const FLEET: &str = "extensions/fleet.md";
|
|
const REVENUE_SHARE: &str = "extensions/revenue-share.md";
|
|
const OPPORTUNITY: &str = "extensions/opportunity-report.md";
|
|
const BROWSER_SINK: &str = "extensions/browser-sink.md";
|
|
const TAKEDOWN: &str = "extensions/takedown.md";
|
|
const INFLUENCE: &str = "extensions/influence.md";
|
|
const DIRECTION: &str = "extensions/direction.md";
|
|
const ACCESS_SERVICES: &str = "extensions/access-services.md";
|
|
const AGE_ASSURANCE: &str = "extensions/age-assurance.md";
|
|
const EXPLORATION: &str = "extensions/exploration.md";
|
|
const EXACT_UPSCALE: &str = "extensions/exact-upscale.md";
|
|
const TELEMETRY_AGGREGATION: &str = "extensions/telemetry-aggregation.md";
|
|
const IMPRESSIONS: &str = "extensions/impression-aggregates.md";
|
|
const EXACT_TONEMAP: &str = "extensions/exact-tonemap.md";
|
|
const ROBUSTNESS: &str = "extensions/robustness-evidence.md";
|
|
const SPLAT_EXACT: &str = "extensions/splat-exact.md";
|
|
const PQ_SIGNATURES: &str = "extensions/pq-signatures.md";
|
|
const PRIOR_CARRIAGE: &str = "extensions/prior-carriage.md";
|
|
const SCENE_CARRIAGE: &str = "extensions/scene-carriage.md";
|
|
const DELIVERY_TELEMETRY: &str = "extensions/delivery-telemetry.md";
|
|
const PROJECTION: &str = "extensions/projection.md";
|
|
const LOC_CARRIAGE: &str = "extensions/loc-carriage.md";
|
|
const STREAM_TERMINATION: &str = "extensions/stream-termination.md";
|
|
const KEY_RELEASE: &str = "extensions/key-release.md";
|
|
const CONFORMANCE_RESULTS: &str = "extensions/conformance-results.md";
|
|
const RUNG_PRICE: &str = "extensions/rung-price.md";
|
|
const ROUTE_RECORD: &str = "extensions/route-record.md";
|
|
|
|
const fn wire(name: &'static str, kind: WireKind, document: &'static str, section: &'static str,
|
|
status: WireStatus) -> WireIdentifier {
|
|
WireIdentifier { name, kind, document, section, status }
|
|
}
|
|
|
|
/// The wire identifiers of the container, of its two delivery bindings
|
|
/// (http-delivery, moq-streaming-format), of the key discovery those bindings serve
|
|
/// (jwp-receipts §7) and of every extension that defines one: grouped by document, each
|
|
/// group in its document's order. The export lists them sorted by name and kind.
|
|
pub const WIRE_IDENTIFIERS: &[WireIdentifier] = &[
|
|
wire("WAI1", WireKind::Magic, "SPEC.md", "§2", WireStatus::Defined),
|
|
wire("WAI2", WireKind::Magic, "SPEC.md", "§7.1", WireStatus::Defined),
|
|
wire("application/wai", WireKind::MediaType, HTTP_DELIVERY, "§3", WireStatus::Proposed),
|
|
wire("wai1", WireKind::CodecsPrefix, HTTP_DELIVERY, "§4.1", WireStatus::Defined),
|
|
wire("wai2", WireKind::CodecsPrefix, HTTP_DELIVERY, "§4.1", WireStatus::Defined),
|
|
wire(".wai", WireKind::Path, HTTP_DELIVERY, "§5.2", WireStatus::Defined),
|
|
wire("WHP1", WireKind::Magic, HTTP_DELIVERY, "§6.2", WireStatus::Defined),
|
|
wire(".wai.hp", WireKind::Path, HTTP_DELIVERY, "§6.2", WireStatus::Defined),
|
|
wire("rcpt/", WireKind::Path, HTTP_DELIVERY, "§8.1", WireStatus::Defined),
|
|
wire(".wai.receipts", WireKind::Path, HTTP_DELIVERY, "§8.2", WireStatus::Defined),
|
|
wire("wai-receipt-index", WireKind::DocumentKind, HTTP_DELIVERY, "§8.2", WireStatus::Defined),
|
|
wire("/.well-known/wai-key-status", WireKind::WellKnown, HTTP_DELIVERY, "§8.4", WireStatus::Defined),
|
|
wire("/.well-known/wai-grants/", WireKind::WellKnown, HTTP_DELIVERY, "§8.4", WireStatus::Defined),
|
|
wire("wai-module-grants", WireKind::DocumentKind, HTTP_DELIVERY, "§8.4", WireStatus::Defined),
|
|
wire("mr/", WireKind::Path, HTTP_DELIVERY, "§8.6", WireStatus::Defined),
|
|
wire("/.well-known/wai-sets/", WireKind::WellKnown, HTTP_DELIVERY, "§8.7", WireStatus::Defined),
|
|
wire("science.transaction.wai.sets", WireKind::DataId, HTTP_DELIVERY, "§8.7", WireStatus::Defined),
|
|
wire("#WAI-LAYER", WireKind::PlaylistTag, HTTP_DELIVERY, "§10.4", WireStatus::Defined),
|
|
wire("science.transaction.wai.multivariant", WireKind::DataId, HTTP_DELIVERY, "§11.1", WireStatus::Defined),
|
|
wire("X-WAI-FLOOR", WireKind::PlaylistAttribute, HTTP_DELIVERY, "§11.1", WireStatus::Defined),
|
|
wire("tag:transaction.science,2026:wai/http-delivery", WireKind::Scheme, HTTP_DELIVERY, "§11.1", WireStatus::Defined),
|
|
wire("tag:transaction.science,2026:wai/floor", WireKind::Scheme, HTTP_DELIVERY, "§11.1", WireStatus::Defined),
|
|
wire("wai1", WireKind::FourCc, HTTP_DELIVERY, "Appendix B", WireStatus::Provisional),
|
|
wire("wai2", WireKind::FourCc, HTTP_DELIVERY, "Appendix B", WireStatus::Provisional),
|
|
wire("waiC", WireKind::FourCc, HTTP_DELIVERY, "Appendix B", WireStatus::Provisional),
|
|
wire("wai", WireKind::Catalog, MOQ_FORMAT, "§3", WireStatus::Defined),
|
|
wire("wai_capabilities", WireKind::Catalog, MOQ_FORMAT, "§4", WireStatus::Defined),
|
|
wire("wai_determinism", WireKind::Catalog, MOQ_FORMAT, "§4", WireStatus::Defined),
|
|
wire("wai_receipts", WireKind::Catalog, MOQ_FORMAT, "§4", WireStatus::Defined),
|
|
wire("wai_receipt_alias", WireKind::Catalog, MOQ_FORMAT, "§4", WireStatus::Defined),
|
|
wire("wai_receipts_track", WireKind::Catalog, MOQ_FORMAT, "§4", WireStatus::Defined),
|
|
wire("wai_priors", WireKind::Catalog, MOQ_FORMAT, "§4.2", WireStatus::Defined),
|
|
wire("wai_staged", WireKind::Catalog, MOQ_FORMAT, "§4.1", WireStatus::Defined),
|
|
wire("wai-receipts", WireKind::Catalog, MOQ_FORMAT, "§4.1", WireStatus::Defined),
|
|
wire("WAI_RECEIPT", WireKind::Catalog, MOQ_FORMAT, "§5", WireStatus::Defined),
|
|
wire("WJR1", WireKind::Magic, JWP_RECEIPTS, "§2.7.3", WireStatus::Defined),
|
|
wire("/.well-known/wai-keys", WireKind::WellKnown, JWP_RECEIPTS, "§7.1", WireStatus::Defined),
|
|
wire("wai-key-status", WireKind::DocumentKind, JWP_RECEIPTS, "§7.9", WireStatus::Defined),
|
|
wire("wai-module-grant", WireKind::DocumentKind, JWP_RECEIPTS, "§7.9", WireStatus::Defined),
|
|
// A node's signed statement of which objects of which groups it holds now.
|
|
wire("WHD1", WireKind::Magic, HOLDINGS, "§4.1", WireStatus::Defined),
|
|
wire("WSIX", WireKind::Magic, PACKAGING, "§6", WireStatus::Defined),
|
|
wire("science.transaction.wai.class", WireKind::DataId, PACKAGING, "§8", WireStatus::Defined),
|
|
wire("science.transaction.wai.stages", WireKind::DataId, PACKAGING, "§8", WireStatus::Defined),
|
|
wire("tag:transaction.science,2026:wai/class", WireKind::Scheme, PACKAGING, "§8", WireStatus::Defined),
|
|
wire("tag:transaction.science,2026:wai/stages", WireKind::Scheme, PACKAGING, "§8", WireStatus::Defined),
|
|
wire("wai_delivery_timeout_ms", WireKind::Catalog, PACKAGING, "§8", WireStatus::Defined),
|
|
wire("WEV1", WireKind::Magic, LIVE_EVENTS, "§3.1", WireStatus::Defined),
|
|
wire("WEP1", WireKind::Magic, LIVE_EVENTS, "§5", WireStatus::Defined),
|
|
wire("urn:wai:event:1", WireKind::Catalog, LIVE_EVENTS, "§8.1", WireStatus::Defined),
|
|
wire("science.transaction.wai.event", WireKind::PlaylistAttribute, LIVE_EVENTS, "§8.3", WireStatus::Defined),
|
|
wire("X-WAI-EVENT", WireKind::PlaylistAttribute, LIVE_EVENTS, "§8.3", WireStatus::Defined),
|
|
wire("urn:wai:event:1", WireKind::Scheme, LIVE_EVENTS, "§8.4", WireStatus::Defined),
|
|
wire("WRD1", WireKind::Magic, LIVE_ROOMS, "§3.1", WireStatus::Defined),
|
|
wire("WRG1", WireKind::Magic, LIVE_ROOMS, "§4.1", WireStatus::Defined),
|
|
wire("WRP1", WireKind::Magic, LIVE_ROOMS, "§10.5.1", WireStatus::Defined),
|
|
wire("GRANT_CHALLENGE", WireKind::SetupOption, LIVE_ROOMS, "§10.5.2", WireStatus::Proposed),
|
|
wire("GRANT_PROOF", WireKind::SetupOption, LIVE_ROOMS, "§10.5.2", WireStatus::Proposed),
|
|
wire("WAI-Room-Proof", WireKind::HttpHeader, LIVE_ROOMS, "§10.5.3", WireStatus::Proposed),
|
|
wire("WAI-Room-Challenge", WireKind::HttpHeader, LIVE_ROOMS, "§10.5.3", WireStatus::Proposed),
|
|
wire("WUR1", WireKind::Magic, CAPTURE_BINDING, "§6.2", WireStatus::Defined),
|
|
wire("WTM1", WireKind::Magic, CAPTURE_BINDING, "§7.1", WireStatus::Defined),
|
|
wire("WCN1", WireKind::Magic, CAPTURE_BINDING, "§8.1", WireStatus::Defined),
|
|
wire("WCD1", WireKind::Magic, LIVE_COMPOSE, "§3.1", WireStatus::Defined),
|
|
wire("WCR1", WireKind::Magic, LIVE_COMPOSE, "§8.1", WireStatus::Defined),
|
|
wire("WRM1", WireKind::Magic, LIVE_RECORDING, "§4.1", WireStatus::Defined),
|
|
wire("WCL1", WireKind::Magic, LIVE_RECORDING, "§5.1", WireStatus::Defined),
|
|
wire("WTX1", WireKind::Magic, TIMED_TEXT, "§4.2", WireStatus::Defined),
|
|
wire("wai_origin", WireKind::Catalog, TIMED_TEXT, "§7.2", WireStatus::Defined),
|
|
wire("wai_model", WireKind::Catalog, TIMED_TEXT, "§7.2", WireStatus::Defined),
|
|
wire("wai_machine_generated", WireKind::Catalog, TIMED_TEXT, "§7.4", WireStatus::Defined),
|
|
wire("tag:transaction.science,2026:wai/model/", WireKind::Scheme, TIMED_TEXT, "§10.3", WireStatus::Defined),
|
|
wire("tag:transaction.science,2026:wai/timed-text", WireKind::Scheme, TIMED_TEXT, "§10.4", WireStatus::Defined),
|
|
wire("science.transaction.wai.timed-text", WireKind::DataId, TIMED_TEXT, "§10.5", WireStatus::Defined),
|
|
wire("WMH1", WireKind::Magic, LIVE_METERING, "§3.1", WireStatus::Defined),
|
|
wire("WMR1", WireKind::Magic, LIVE_METERING, "§4.1", WireStatus::Defined),
|
|
wire("WSP1", WireKind::Magic, ENERGY_STEERING, "§3.1", WireStatus::Defined),
|
|
wire("WSD1", WireKind::Magic, ENERGY_STEERING, "§7.1", WireStatus::Defined),
|
|
wire("WLK1", WireKind::Magic, LIVE_CONTRIBUTION, "§6.2", WireStatus::Defined),
|
|
wire("WMP1", WireKind::Magic, LIVE_MODERATION, "§3.1", WireStatus::Defined),
|
|
wire("WMS1", WireKind::Magic, LIVE_MODERATION, "§4.2", WireStatus::Defined),
|
|
wire("WMN1", WireKind::Magic, LIVE_MODERATION, "§5.1", WireStatus::Defined),
|
|
wire("WRE1", WireKind::Magic, CONFIDENTIALITY, "§3.1", WireStatus::Defined),
|
|
wire("SECURE_OBJECT_KEY_ID", WireKind::Catalog, CONFIDENTIALITY, "§4.3", WireStatus::Defined),
|
|
wire("WAI_INNER_DIGEST", WireKind::Catalog, CONFIDENTIALITY, "§4.4", WireStatus::Defined),
|
|
wire("WMC1", WireKind::Magic, LIVE_MESSAGING, "§3.1", WireStatus::Defined),
|
|
wire("WMG1", WireKind::Magic, LIVE_MESSAGING, "§5.1", WireStatus::Defined),
|
|
wire("WME1", WireKind::Magic, LIVE_MESSAGING, "§7.3", WireStatus::Defined),
|
|
wire("WMA1", WireKind::Magic, LIVE_MESSAGING, "§8", WireStatus::Defined),
|
|
wire("WCT1", WireKind::Magic, LIVE_MESSAGING, "§10.1", WireStatus::Defined),
|
|
wire("WCI1", WireKind::Magic, LIVE_MESSAGING, "§10.2", WireStatus::Defined),
|
|
wire("WCA1", WireKind::Magic, LIVE_MESSAGING, "§10.3", WireStatus::Defined),
|
|
wire("WWS1", WireKind::Magic, FORENSIC_WATERMARK, "§5.1", WireStatus::Defined),
|
|
wire("WWQ1", WireKind::Magic, FORENSIC_WATERMARK, "§7.1", WireStatus::Defined),
|
|
wire("WWD1", WireKind::Magic, FORENSIC_WATERMARK, "§8.1", WireStatus::Defined),
|
|
wire("WAP1", WireKind::Magic, LIVE_ADS, "§3.1", WireStatus::Defined),
|
|
wire("WAB1", WireKind::Magic, LIVE_ADS, "§4.2", WireStatus::Defined),
|
|
wire("WPC1", WireKind::Magic, AD_PRESENTATION, "§5.1", WireStatus::Defined),
|
|
wire("WSI1", WireKind::Magic, STITCHED_PRESENTATION, "§4.1", WireStatus::Defined),
|
|
wire("WSC1", WireKind::Magic, STITCHED_PRESENTATION, "§5.1", WireStatus::Defined),
|
|
wire("WLU1", WireKind::Magic, CHANNEL_LINEUP, "§6.1", WireStatus::Defined),
|
|
wire("wai-channel-feed", WireKind::DocumentKind, CHANNEL_LINEUP, "§4.4", WireStatus::Defined),
|
|
wire("urn:wai:guide:", WireKind::Scheme, CHANNEL_LINEUP, "§7.2", WireStatus::Defined),
|
|
wire("wai-asset-id", WireKind::Scheme, CHANNEL_LINEUP, "§7.2", WireStatus::Defined),
|
|
wire("wai-now-next", WireKind::DocumentKind, CHANNEL_LINEUP, "§7.3", WireStatus::Defined),
|
|
wire("WXP1", WireKind::Magic, CO_WATCH, "§3.1", WireStatus::Defined),
|
|
wire("WXC1", WireKind::Magic, CO_WATCH, "§5.1", WireStatus::Defined),
|
|
wire("WXS1", WireKind::Magic, CO_WATCH, "§7.1", WireStatus::Defined),
|
|
wire("WXK1", WireKind::Magic, CO_WATCH, "§8.4", WireStatus::Defined),
|
|
wire("WDS1", WireKind::Magic, REMOTE_DESKTOP, "§3.3", WireStatus::Defined),
|
|
wire("WDI1", WireKind::Magic, REMOTE_DESKTOP, "§5.1", WireStatus::Defined),
|
|
wire("WDO1", WireKind::Magic, REMOTE_DESKTOP, "§6.1", WireStatus::Defined),
|
|
wire("WDF1", WireKind::Magic, REMOTE_DESKTOP, "§7.2", WireStatus::Defined),
|
|
wire("WDL1", WireKind::Magic, REMOTE_DESKTOP, "§8.1", WireStatus::Defined),
|
|
wire("wai_c2pa_track", WireKind::Catalog, LIVE_PROVENANCE, "§10.2", WireStatus::Defined),
|
|
wire("wai-c2pa", WireKind::Catalog, LIVE_PROVENANCE, "§10.2", WireStatus::Defined),
|
|
wire("wai-derivation", WireKind::DocumentKind, DERIVING_EDGE, "§5.1", WireStatus::Defined),
|
|
wire("wai-origin", WireKind::DocumentKind, SYNTHESIS, "§3.1", WireStatus::Defined),
|
|
wire("wai-marking", WireKind::DocumentKind, SYNTHESIS, "§7.2", WireStatus::Defined),
|
|
wire("wai-detection", WireKind::DocumentKind, SYNTHESIS, "§7.3", WireStatus::Defined),
|
|
wire("wai-review", WireKind::DocumentKind, SYNTHESIS, "§9.1", WireStatus::Defined),
|
|
wire("wai-label-policy", WireKind::DocumentKind, SYNTHESIS, "§10.1", WireStatus::Defined),
|
|
wire("wai-player", WireKind::DocumentKind, SYNTHESIS, "§10.3", WireStatus::Defined),
|
|
wire("wai-mark:tent64", WireKind::Scheme, SYNTHESIS, "§7.4", WireStatus::Defined),
|
|
wire("wai-mark:tent64s", WireKind::Scheme, SYNTHESIS, "§7.4", WireStatus::Defined),
|
|
wire("wai-mark:conformance", WireKind::Scheme, SYNTHESIS, "§7.4", WireStatus::Defined),
|
|
wire("/.well-known/wai-mark/", WireKind::WellKnown, SYNTHESIS, "§7.7", WireStatus::Proposed),
|
|
wire("WSR1", WireKind::Magic, EXACT_UPSCALE, "§3.1", WireStatus::Defined),
|
|
wire("WSK1", WireKind::Magic, PRIOR_CARRIAGE, "§18.2", WireStatus::Defined),
|
|
wire("wai-set-usage", WireKind::DocumentKind, PRIOR_CARRIAGE, "§18.1", WireStatus::Defined),
|
|
wire("wai-usage.json", WireKind::Path, PRIOR_CARRIAGE, "§18.1", WireStatus::Defined),
|
|
wire("WTR1", WireKind::Magic, PRIOR_CARRIAGE, "§19", WireStatus::Defined),
|
|
wire("wai-upscale", WireKind::DocumentKind, EXACT_UPSCALE, "§4.2", WireStatus::Defined),
|
|
wire("wai-presentation", WireKind::DocumentKind, EXACT_UPSCALE, "§6.2", WireStatus::Defined),
|
|
wire("wai-int/1", WireKind::Scheme, PRIOR_CARRIAGE, "§10", WireStatus::Defined),
|
|
wire("wsr1/1", WireKind::Scheme, PRIOR_CARRIAGE, "§10.2", WireStatus::Defined),
|
|
wire("whm1/1", WireKind::Scheme, PRIOR_CARRIAGE, "§10.2", WireStatus::Defined),
|
|
wire("wai-scene/1", WireKind::Scheme, SCENE_CARRIAGE, "§2.3", WireStatus::Defined),
|
|
wire("urn:wai:asset:", WireKind::Scheme, SCENE_CARRIAGE, "§2.2", WireStatus::Defined),
|
|
wire("WAU1", WireKind::Magic, AI_USAGE, "§4.2", WireStatus::Defined),
|
|
wire("wai_ai_usage", WireKind::Catalog, MOQ_FORMAT, "§4", WireStatus::Defined),
|
|
wire("WAI-Usage-Claim", WireKind::HttpHeader, AI_USAGE, "§7.3", WireStatus::Proposed),
|
|
wire("wai-session", WireKind::DocumentKind, CONTRIBUTION, "§3.1", WireStatus::Defined),
|
|
wire("wai-membership", WireKind::DocumentKind, CONTRIBUTION, "§3.2", WireStatus::Defined),
|
|
wire("wai-step", WireKind::DocumentKind, CONTRIBUTION, "§4.1", WireStatus::Defined),
|
|
wire("wai-contribution", WireKind::DocumentKind, CONTRIBUTION, "§6", WireStatus::Defined),
|
|
wire("wai-authorship-map", WireKind::DocumentKind, CONTRIBUTION, "§7.3", WireStatus::Defined),
|
|
wire("WDA1", WireKind::Magic, SETTLEMENT, "§3.1", WireStatus::Defined),
|
|
wire("WBR1", WireKind::Magic, SETTLEMENT, "§5.2", WireStatus::Defined),
|
|
wire("WSS1", WireKind::Magic, SETTLEMENT, "§7.1", WireStatus::Defined),
|
|
wire("WLT1", WireKind::Magic, LEDGER, "§4.1", WireStatus::Defined),
|
|
wire("WLI1", WireKind::Magic, LEDGER, "§6.1", WireStatus::Defined),
|
|
wire("WAS1", WireKind::Magic, STREAM_AUDIT, "§5.1", WireStatus::Defined),
|
|
wire("WFE1", WireKind::Magic, FLEET, "§3.1", WireStatus::Defined),
|
|
wire("WFR1", WireKind::Magic, FLEET, "§6.1", WireStatus::Defined),
|
|
wire("wai-fleet-bundle", WireKind::DocumentKind, FLEET, "§7.1", WireStatus::Defined),
|
|
wire(".wai-fleet.json", WireKind::Path, FLEET, "§7.1", WireStatus::Defined),
|
|
wire("wai-rung-prices", WireKind::DocumentKind, RUNG_PRICE, "§4.1", WireStatus::Defined),
|
|
wire("wai-rung-request", WireKind::DocumentKind, RUNG_PRICE, "§6.1", WireStatus::Defined),
|
|
wire("wai-route-request", WireKind::DocumentKind, ROUTE_RECORD, "§3.1", WireStatus::Defined),
|
|
wire("wai-route-pricebook", WireKind::DocumentKind, ROUTE_RECORD, "§3.2", WireStatus::Defined),
|
|
wire("wai-route-policy", WireKind::DocumentKind, ROUTE_RECORD, "§3.3", WireStatus::Defined),
|
|
wire("wai-route-record", WireKind::DocumentKind, ROUTE_RECORD, "§5.1", WireStatus::Defined),
|
|
wire("wai-route-third-party-hop", WireKind::DocumentKind, ROUTE_RECORD, "§6.2", WireStatus::Defined),
|
|
wire("wai-route-delivery-decision", WireKind::DocumentKind, ROUTE_RECORD, "§6.3", WireStatus::Defined),
|
|
wire("WRC1", WireKind::Magic, REVENUE_SHARE, "§3.1", WireStatus::Defined),
|
|
wire("WRS1", WireKind::Magic, REVENUE_SHARE, "§7.1", WireStatus::Defined),
|
|
wire("WOR1", WireKind::Magic, OPPORTUNITY, "§7.1", WireStatus::Defined),
|
|
wire("WCK1", WireKind::Magic, OPPORTUNITY, "§10.1", WireStatus::Defined),
|
|
wire("contentBinding", WireKind::FrameMetadata, BROWSER_SINK, "§7.1", WireStatus::Proposed),
|
|
wire("wai-takedown-clocks", WireKind::DocumentKind, TAKEDOWN, "§4", WireStatus::Defined),
|
|
wire("wai-takedown-policy", WireKind::DocumentKind, TAKEDOWN, "§5.1", WireStatus::Defined),
|
|
wire("wai-takedown-notice", WireKind::DocumentKind, TAKEDOWN, "§5.2", WireStatus::Defined),
|
|
wire("wai-takedown", WireKind::DocumentKind, TAKEDOWN, "§5.3", WireStatus::Defined),
|
|
wire("wai-takedown-match", WireKind::DocumentKind, TAKEDOWN, "§5.4", WireStatus::Defined),
|
|
wire("wai-takedown-purge", WireKind::DocumentKind, TAKEDOWN, "§5.5", WireStatus::Defined),
|
|
wire("wai-takedown-counts", WireKind::DocumentKind, TAKEDOWN, "§5.6", WireStatus::Defined),
|
|
wire("WPP1", WireKind::Magic, CO_PERFORMANCE, "§3.1", WireStatus::Defined),
|
|
wire("WPI1", WireKind::Magic, CO_PERFORMANCE, "§5.1", WireStatus::Defined),
|
|
wire("WPF1", WireKind::Magic, CO_PERFORMANCE, "§5.6", WireStatus::Defined),
|
|
wire("WPT1", WireKind::Magic, CO_PERFORMANCE, "§6.1", WireStatus::Defined),
|
|
wire("WPH1", WireKind::Magic, CO_PERFORMANCE, "§6.3", WireStatus::Defined),
|
|
wire("WPM1", WireKind::Magic, CO_PERFORMANCE, "§6.7", WireStatus::Defined),
|
|
wire("WPW1", WireKind::Magic, CO_PERFORMANCE, "§7.2", WireStatus::Defined),
|
|
wire("WPA1", WireKind::Magic, CO_PERFORMANCE, "§7.3", WireStatus::Defined),
|
|
wire("WPK1", WireKind::Magic, CO_PERFORMANCE, "§7.5", WireStatus::Defined),
|
|
wire("WPS1", WireKind::Magic, CO_PERFORMANCE, "§7.7", WireStatus::Defined),
|
|
wire("wai-terms", WireKind::DocumentKind, INFLUENCE, "§3.2", WireStatus::Defined),
|
|
wire("wai-catalogue", WireKind::DocumentKind, INFLUENCE, "§3.3", WireStatus::Defined),
|
|
wire("wai-conditioning", WireKind::DocumentKind, INFLUENCE, "§4.1", WireStatus::Defined),
|
|
wire("wai-attribution", WireKind::DocumentKind, INFLUENCE, "§5.3", WireStatus::Defined),
|
|
wire("wai-influence-report", WireKind::DocumentKind, INFLUENCE, "§7.1", WireStatus::Defined),
|
|
wire("wai-storyboard", WireKind::DocumentKind, DIRECTION, "§4", WireStatus::Defined),
|
|
wire("wai-keyframes", WireKind::DocumentKind, DIRECTION, "§5", WireStatus::Defined),
|
|
wire("wai-sequence", WireKind::DocumentKind, DIRECTION, "§6", WireStatus::Defined),
|
|
wire("wai-directed", WireKind::DocumentKind, DIRECTION, "§8.1", WireStatus::Defined),
|
|
wire("wai-caption-sources", WireKind::DocumentKind, ACCESS_SERVICES, "§4.2", WireStatus::Defined),
|
|
wire("wai-caption-reference", WireKind::DocumentKind, ACCESS_SERVICES, "§4.3", WireStatus::Defined),
|
|
wire("wai-caption-quality", WireKind::DocumentKind, ACCESS_SERVICES, "§4.7", WireStatus::Defined),
|
|
wire("wai-description", WireKind::DocumentKind, ACCESS_SERVICES, "§5.1", WireStatus::Defined),
|
|
wire("tag:transaction.science,2026:wai/access", WireKind::Scheme, ACCESS_SERVICES, "§5.5", WireStatus::Defined),
|
|
wire("wai-signing", WireKind::DocumentKind, ACCESS_SERVICES, "§6.1", WireStatus::Defined),
|
|
wire("wai-signing-review", WireKind::DocumentKind, ACCESS_SERVICES, "§6.4", WireStatus::Defined),
|
|
wire("wai-access-completeness", WireKind::DocumentKind, ACCESS_SERVICES, "§7.1", WireStatus::Defined),
|
|
wire("wai-rating", WireKind::DocumentKind, AGE_ASSURANCE, "§3.1", WireStatus::Defined),
|
|
wire("wai-age-policy", WireKind::DocumentKind, AGE_ASSURANCE, "§4.1", WireStatus::Defined),
|
|
wire("wai-age-admissions", WireKind::DocumentKind, AGE_ASSURANCE, "§7.1", WireStatus::Defined),
|
|
// A rating claim as a MOQT Track or Object Property, type 0x3A4D, in the range MOQT §8.4
|
|
// leaves to applications.
|
|
wire("WAI_RATING", WireKind::Catalog, AGE_ASSURANCE, "§5.7", WireStatus::Defined),
|
|
wire("wai-archive", WireKind::DocumentKind, EXPLORATION, "§5.3", WireStatus::Defined),
|
|
wire("wai-distance", WireKind::DocumentKind, EXPLORATION, "§6.3", WireStatus::Defined),
|
|
wire("wai-collection", WireKind::DocumentKind, EXPLORATION, "§7.1", WireStatus::Defined),
|
|
wire("wai-taste", WireKind::DocumentKind, EXPLORATION, "§8.1", WireStatus::Defined),
|
|
wire("wai-ranking", WireKind::DocumentKind, EXPLORATION, "§9.1", WireStatus::Defined),
|
|
wire("wai-pick", WireKind::DocumentKind, EXPLORATION, "§10.2", WireStatus::Defined),
|
|
wire("WQS1", WireKind::Magic, TELEMETRY_AGGREGATION, "§6.1", WireStatus::Defined),
|
|
wire("WQA1", WireKind::Magic, TELEMETRY_AGGREGATION, "§7.1", WireStatus::Defined),
|
|
wire("WIC1", WireKind::Magic, IMPRESSIONS, "§4.1", WireStatus::Defined),
|
|
wire("WIT1", WireKind::Magic, IMPRESSIONS, "§5.4", WireStatus::Defined),
|
|
wire("WIU1", WireKind::Magic, IMPRESSIONS, "§6.4", WireStatus::Defined),
|
|
wire("wai_impression_token", WireKind::DapReportExtension, IMPRESSIONS, "§7.2", WireStatus::Proposed),
|
|
wire("WGM1", WireKind::Magic, EXACT_TONEMAP, "§4.1", WireStatus::Defined),
|
|
wire("WD50", WireKind::Magic, EXACT_TONEMAP, "§5.1", WireStatus::Defined),
|
|
wire("wai-tonemap", WireKind::DocumentKind, EXACT_TONEMAP, "§7.1", WireStatus::Defined),
|
|
wire("wai-robustness-corpus", WireKind::DocumentKind, ROBUSTNESS, "§3", WireStatus::Defined),
|
|
wire("wai-attack:", WireKind::Scheme, ROBUSTNESS, "§4", WireStatus::Defined),
|
|
wire("wai-robustness", WireKind::DocumentKind, ROBUSTNESS, "§5", WireStatus::Defined),
|
|
wire("wai-robustness-harness:1", WireKind::Scheme, ROBUSTNESS, "§6", WireStatus::Defined),
|
|
wire("wai-robustness-claim", WireKind::DocumentKind, ROBUSTNESS, "§8", WireStatus::Defined),
|
|
wire("EXT_gaussian_splatting_compression_wai", WireKind::GltfExtension, SPLAT_EXACT, "§3.2", WireStatus::Proposed),
|
|
wire("wai-splat-render:i1", WireKind::Scheme, SPLAT_EXACT, "§5", WireStatus::Defined),
|
|
wire("wai-splat-commitment", WireKind::DocumentKind, SPLAT_EXACT, "§6.1", WireStatus::Defined),
|
|
wire("wai-splat-view", WireKind::DocumentKind, SPLAT_EXACT, "§7", WireStatus::Defined),
|
|
// The suite a hybrid record names in its `pq_suite`: the composite of
|
|
// draft-ietf-lamps-pq-composite-sigs-19 §6, which pq-signatures §2 adopts.
|
|
wire("id-MLDSA65-Ed25519-SHA512", WireKind::Scheme, PQ_SIGNATURES, "§2", WireStatus::Defined),
|
|
// The custom keys of delivery telemetry's CMCD and CMSD reports.
|
|
wire("science.transaction.wai-b", WireKind::TelemetryKey, DELIVERY_TELEMETRY, "§10", WireStatus::Defined),
|
|
wire("science.transaction.wai-tx", WireKind::TelemetryKey, DELIVERY_TELEMETRY, "§10", WireStatus::Defined),
|
|
wire("science.transaction.wai-ch", WireKind::TelemetryKey, DELIVERY_TELEMETRY, "§10", WireStatus::Defined),
|
|
wire("science.transaction.wai-cap", WireKind::TelemetryKey, DELIVERY_TELEMETRY, "§10", WireStatus::Defined),
|
|
wire("science.transaction.wai-ri", WireKind::TelemetryKey, DELIVERY_TELEMETRY, "§10", WireStatus::Defined),
|
|
wire("science.transaction.wai-l", WireKind::TelemetryKey, DELIVERY_TELEMETRY, "§10", WireStatus::Defined),
|
|
wire("science.transaction.wai-lt", WireKind::TelemetryKey, DELIVERY_TELEMETRY, "§10", WireStatus::Defined),
|
|
wire("science.transaction.wai-p", WireKind::TelemetryKey, DELIVERY_TELEMETRY, "§10", WireStatus::Defined),
|
|
wire("science.transaction.wai-rcpt", WireKind::TelemetryKey, DELIVERY_TELEMETRY, "§10", WireStatus::Defined),
|
|
wire("science.transaction.wai-lc", WireKind::TelemetryKey, DELIVERY_TELEMETRY, "§10", WireStatus::Defined),
|
|
wire("science.transaction.wai-lcf", WireKind::TelemetryKey, DELIVERY_TELEMETRY, "§10", WireStatus::Defined),
|
|
wire("science.transaction.wai-coh", WireKind::TelemetryKey, DELIVERY_TELEMETRY, "§10", WireStatus::Defined),
|
|
wire("science.transaction.wai-u", WireKind::TelemetryKey, DELIVERY_TELEMETRY, "§10", WireStatus::Defined),
|
|
wire("science.transaction.wai-pl", WireKind::TelemetryKey, DELIVERY_TELEMETRY, "§10", WireStatus::Defined),
|
|
wire("science.transaction.wai-late", WireKind::TelemetryKey, DELIVERY_TELEMETRY, "§10", WireStatus::Defined),
|
|
wire("science.transaction.wai-dec", WireKind::TelemetryKey, DELIVERY_TELEMETRY, "§10", WireStatus::Defined),
|
|
wire("science.transaction.wai-sw", WireKind::TelemetryKey, DELIVERY_TELEMETRY, "§10", WireStatus::Defined),
|
|
wire("science.transaction.wai-co", WireKind::TelemetryKey, DELIVERY_TELEMETRY, "§10", WireStatus::Defined),
|
|
wire("science.transaction.wai-cr", WireKind::TelemetryKey, DELIVERY_TELEMETRY, "§10", WireStatus::Defined),
|
|
wire("science.transaction.wai-cf", WireKind::TelemetryKey, DELIVERY_TELEMETRY, "§10", WireStatus::Defined),
|
|
wire("science.transaction.wai-clm", WireKind::TelemetryKey, DELIVERY_TELEMETRY, "§10", WireStatus::Defined),
|
|
wire("science.transaction.wai-op", WireKind::TelemetryKey, DELIVERY_TELEMETRY, "§10", WireStatus::Defined),
|
|
wire("science.transaction.wai-drop", WireKind::TelemetryKey, DELIVERY_TELEMETRY, "§10", WireStatus::Defined),
|
|
wire("WPJ1", WireKind::Magic, PROJECTION, "§3", WireStatus::Defined),
|
|
// An envelope's manifest as an Immutable Property of a LOC object, type 0x3A61, in the
|
|
// range MOQT §8.4 leaves to applications.
|
|
wire("WAI_MANIFEST", WireKind::Catalog, LOC_CARRIAGE, "§4", WireStatus::Defined),
|
|
wire("WSL1", WireKind::Magic, STREAM_TERMINATION, "§3.1", WireStatus::Defined),
|
|
wire("WKL1", WireKind::Magic, KEY_RELEASE, "§4.1", WireStatus::Defined),
|
|
wire("WKE1", WireKind::Magic, KEY_RELEASE, "§5.1", WireStatus::Defined),
|
|
wire("WAI-Key-Ids", WireKind::HttpHeader, KEY_RELEASE, "§6.2", WireStatus::Proposed),
|
|
wire("WAI-Key-Kind", WireKind::HttpHeader, KEY_RELEASE, "§6.2", WireStatus::Proposed),
|
|
wire("WAI-Key-Renews", WireKind::HttpHeader, KEY_RELEASE, "§6.2", WireStatus::Proposed),
|
|
wire("WAI-Key-Time", WireKind::HttpHeader, KEY_RELEASE, "§6.2", WireStatus::Proposed),
|
|
wire("WAI-Key-Entitlement", WireKind::HttpHeader, KEY_RELEASE, "§6.2", WireStatus::Proposed),
|
|
wire("WAI-Key-Proof", WireKind::HttpHeader, KEY_RELEASE, "§6.2", WireStatus::Proposed),
|
|
wire("WAI-Key-Receipt", WireKind::HttpHeader, KEY_RELEASE, "§6.2", WireStatus::Proposed),
|
|
wire("WAI-Key-Licence-Expiry", WireKind::HttpHeader, KEY_RELEASE, "§9.2", WireStatus::Proposed),
|
|
wire("WKT1", WireKind::Magic, KEY_RELEASE, "§9.3", WireStatus::Defined),
|
|
// The signed outcome of a conformance run, its `wai` member's value.
|
|
wire("conform-result/1", WireKind::DocumentKind, CONFORMANCE_RESULTS, "§2", WireStatus::Defined),
|
|
];
|
|
|
|
/// A string with the shape of a capability that the reference implementation uses
|
|
/// as a label but that no revision registers, and why.
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
pub struct UnregisteredLabel {
|
|
pub label: &'static str,
|
|
pub reason: &'static str,
|
|
}
|
|
|
|
const QUANTUM_RECORD_LABEL: &str = "a receipt-kind label the wai-quantum crate seals; no revision of SPEC or of an extension registers it, so it is not a registered record";
|
|
|
|
/// Every [`UnregisteredLabel`]. The strings are copies of
|
|
/// `wai_quantum::quantum_ops::CAP_QUANTUM_{MITIGATE,DECODE,COMPILE,REARRANGE,QBOM,FABRIC}`;
|
|
/// a test under the `quantum_ops` feature holds them equal.
|
|
pub const UNREGISTERED_LABELS: &[UnregisteredLabel] = &[
|
|
UnregisteredLabel { label: "wai.quantum.mitigate", reason: QUANTUM_RECORD_LABEL },
|
|
UnregisteredLabel { label: "wai.quantum.decode", reason: QUANTUM_RECORD_LABEL },
|
|
UnregisteredLabel { label: "wai.quantum.compile", reason: QUANTUM_RECORD_LABEL },
|
|
UnregisteredLabel { label: "wai.quantum.rearrange", reason: QUANTUM_RECORD_LABEL },
|
|
UnregisteredLabel { label: "wai.quantum.qbom", reason: QUANTUM_RECORD_LABEL },
|
|
UnregisteredLabel { label: "wai.quantum.fabric", reason: QUANTUM_RECORD_LABEL },
|
|
];
|
|
|
|
/// One registered string with every property the registry gives it.
|
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
pub struct Registration {
|
|
pub capability: &'static str,
|
|
pub kind: Kind,
|
|
pub status: RegistrationStatus,
|
|
/// The media class, for a payload or companion capability.
|
|
pub media: Option<Media>,
|
|
/// `standalone`, `companion`, `enhancement` or `refinement`, for a payload,
|
|
/// companion or refinement capability ([`capability_role`]).
|
|
pub role: Option<&'static str>,
|
|
pub tier: Option<FidelityTier>,
|
|
pub licence: Option<LicenseClass>,
|
|
pub replicate: Option<ReplicateClass>,
|
|
pub floor: bool,
|
|
pub recommended: bool,
|
|
pub spec_section: &'static str,
|
|
/// See [`ROWS`]: a designation, or `None` for the edition current at `registered`.
|
|
pub edition: Option<&'static str>,
|
|
pub registered: &'static str,
|
|
/// The integer operator set the capability decodes through, if it does
|
|
/// (`extensions/integer-operators.md` §11).
|
|
pub ops: Option<super::OpsMember>,
|
|
}
|
|
|
|
/// Every registered string — payload, companion, derivation and record — sorted
|
|
/// by string.
|
|
pub fn registrations() -> Vec<Registration> {
|
|
let mut v: Vec<Registration> = ROWS
|
|
.iter()
|
|
.map(|&(cap, section, edition, registered)| Registration {
|
|
capability: cap,
|
|
kind: capability_kind(cap).expect("every row is registered"),
|
|
status: capability_status(cap).expect("every row is registered"),
|
|
media: capability_media(cap),
|
|
role: capability_role(cap),
|
|
tier: capability_tier(cap),
|
|
licence: capability_license(cap),
|
|
replicate: capability_replicate_class(cap),
|
|
floor: mandatory_floor().contains(&cap),
|
|
recommended: recommended_set().contains(&cap),
|
|
spec_section: section,
|
|
edition,
|
|
registered,
|
|
ops: super::capability_ops(cap),
|
|
})
|
|
.collect();
|
|
for op in derivation::derivation_operations() {
|
|
v.push(Registration {
|
|
capability: op.capability,
|
|
kind: Kind::Derivation,
|
|
status: RegistrationStatus::Registered,
|
|
media: None,
|
|
role: None,
|
|
tier: None,
|
|
licence: Some(derivation::derivation_license()),
|
|
replicate: None,
|
|
floor: false,
|
|
recommended: false,
|
|
spec_section: S_PRIOR,
|
|
edition: Some("ISO/IEC 23001-16:2021"),
|
|
registered: DERIVATIONS_REGISTERED,
|
|
ops: None,
|
|
});
|
|
}
|
|
v.sort_by(|a, b| a.capability.cmp(b.capability));
|
|
v
|
|
}
|
|
|
|
/// The [`Kind`] of a registered string, or `None` for a string this revision does
|
|
/// not register.
|
|
pub fn capability_kind(cap: &str) -> Option<Kind> {
|
|
if is_known_capability(cap) {
|
|
Some(if is_companion_only(cap) {
|
|
Kind::Companion
|
|
} else if is_refinement_only(cap) {
|
|
Kind::Refinement
|
|
} else {
|
|
Kind::Payload
|
|
})
|
|
} else if derivation::is_derivation_operation(cap) {
|
|
Some(Kind::Derivation)
|
|
} else if RECORDS.contains(&cap) {
|
|
Some(Kind::Record)
|
|
} else {
|
|
None
|
|
}
|
|
}
|
|
|
|
/// The [`RegistrationStatus`] of a registered string, or `None` for a string this
|
|
/// revision does not register.
|
|
pub fn capability_status(cap: &str) -> Option<RegistrationStatus> {
|
|
capability_kind(cap)?;
|
|
Some(if CANDIDATES.contains(&cap) { RegistrationStatus::Candidate } else { RegistrationStatus::Registered })
|
|
}
|
|
|
|
/// Whether a registered capability is a **candidate**: its string is registered but
|
|
/// no revision has pinned its payload format (SPEC §5, *Candidate capabilities*).
|
|
/// Until one does, an encoder MUST NOT emit it and a sink MUST treat it as
|
|
/// unsupported. False for a string this revision does not register.
|
|
pub fn is_candidate(cap: &str) -> bool {
|
|
capability_status(cap) == Some(RegistrationStatus::Candidate)
|
|
}
|
|
|
|
/// Whether a sink may dispatch or select `cap`, as far as this revision's
|
|
/// registry decides. False for every string this revision registers as something
|
|
/// that is not a pinned payload: a companion-only capability (applied with a base,
|
|
/// never on its own), a refinement-only capability (applied to the stage below it,
|
|
/// never on its own; `extensions/staged-delivery.md` §4 processes it), a candidate
|
|
/// (SPEC §5, *Candidate capabilities*), a record and a derivation (neither names a
|
|
/// payload format). True for a registered payload
|
|
/// capability whose payload is pinned, and for a string this revision does not
|
|
/// register: a later MINOR revision may register it (SPEC §8), and whether a sink
|
|
/// can decode it is the sink's to say through what it advertises (SPEC §4, step 3).
|
|
///
|
|
/// Every dispatch and selection function of the reference implementation uses this
|
|
/// one predicate, together with what the sink advertises and, where a pin applies,
|
|
/// the sink's verification of it (`Wai::dispatch_verified`, `WaiMulti::pick`,
|
|
/// `WaiMulti::primary`, `RenditionMeta::is_selectable`, the neural sink's
|
|
/// `decode_multi`, the C `wai_envelope_select`, wai-web's `core` module, the CLI's
|
|
/// `inspect`); a new one must use it too.
|
|
pub fn is_dispatchable(cap: &str) -> bool {
|
|
match capability_kind(cap) {
|
|
None => true,
|
|
Some(Kind::Payload) => !is_candidate(cap),
|
|
Some(Kind::Companion | Kind::Refinement | Kind::Derivation | Kind::Record) => false,
|
|
}
|
|
}
|
|
|
|
/// The [`Media`] class of a payload or companion capability, or `None` for any
|
|
/// other string (a record, a derivation, an unregistered string).
|
|
pub fn capability_media(cap: &str) -> Option<Media> {
|
|
use Media::*;
|
|
if !is_known_capability(cap) {
|
|
return None;
|
|
}
|
|
Some(match cap {
|
|
// Learned and generative image paths, and the semantic paths, which
|
|
// regenerate an image.
|
|
CAP_NEURAL_BMSHJ2018 | CAP_NEURAL_MBT2018_MEAN | CAP_NEURAL_INT_SYNTH
|
|
| CAP_NEURAL_INT_HYPER | CAP_NEURAL_INT_MLICPP | CAP_NEURAL_ELIC
|
|
| CAP_NEURAL_MLICPP | CAP_NEURAL_MLICV2 | CAP_NEURAL_CMIC | CAP_NEURAL_GLC
|
|
| CAP_GENERATE_SPECTRAL | CAP_SEMANTIC_CLIP | CAP_SEMANTIC_PERCO2 => Image,
|
|
CAP_NEURAL_ENCODEC32 | CAP_NEURAL_DAC | CAP_NEURAL_MIMI | CAP_NEURAL_WAVTOKENIZER
|
|
| CAP_NEURAL_SNAC => Audio,
|
|
// The neural video codecs and the films (linear-film gives a film's media
|
|
// the value "video").
|
|
CAP_NEURAL_VIDEO_BMSHJ2018 | CAP_NEURAL_DCVC_RT | CAP_NEURAL_DCVC_FM
|
|
| CAP_FILM_LINEAR | CAP_FILM_REEL => Video,
|
|
CAP_WORLD_SCENE | CAP_WORLD_REPLAY | CAP_WORLD_LIVE | CAP_WORLD_MODEL
|
|
| CAP_FEED_STATE | CAP_AVATAR_POSE | CAP_AVATAR_FACE => Interactive,
|
|
CAP_PRIOR_NNC | CAP_PRIOR_SET | CAP_PRIOR_SAFETENSORS | CAP_PRIOR_GGUF | CAP_PRIOR_SEALED | CAP_PRIOR_TREE | CAP_TENSOR_NNC | CAP_QUANTUM_CIRCUIT | CAP_QUANTUM_CIRCUIT2
|
|
| CAP_TERNARY_TT => Binary,
|
|
c if c.starts_with("wai.image.") => Image,
|
|
c if c.starts_with("wai.audio.") => Audio,
|
|
c if c.starts_with("wai.video.") => Video,
|
|
c if c.starts_with("wai.text.") => Text,
|
|
c if c.starts_with("wai.mesh.") || c.starts_with("wai.pc.") || c.starts_with("wai.splat.") => Volumetric,
|
|
c if c.starts_with("wai.haptic.") => Haptic,
|
|
c if c.starts_with("wai.meta.") => Metadata,
|
|
_ => return None,
|
|
})
|
|
}
|
|
|
|
// ---- The export ------------------------------------------------------------------
|
|
|
|
/// Where the specification lives on the forge; the export's `$id`s are under it.
|
|
const FORGE_TREE: &str = "https://git.transaction.science/Transaction-Science/open-standards/src/branch/main/wai";
|
|
/// The namespace of the generated vocabulary.
|
|
pub const VOCAB_V2_NS: &str = "https://wai.transaction.science/vocab/v2#";
|
|
|
|
/// The marker lines between which `wai/REGISTRY.md` carries the generated table.
|
|
pub const REGISTRY_MD_BEGIN: &str = "<!-- generated: wai registry export; do not edit by hand -->";
|
|
pub const REGISTRY_MD_END: &str = "<!-- end generated -->";
|
|
|
|
/// The files `wai registry export` writes, as `(path relative to wai/, contents)`.
|
|
/// `REGISTRY.md` is not among them: only its generated region is (see
|
|
/// [`splice_registry_md`]).
|
|
pub fn export_files() -> Vec<(&'static str, String)> {
|
|
vec![
|
|
("registry/capabilities.json", capabilities_json()),
|
|
("registry/capabilities.schema.json", capabilities_schema()),
|
|
("vocab/v2.ttl", vocab_v2_ttl()),
|
|
("vocab/v2.jsonld", vocab_v2_jsonld()),
|
|
("vocab/v2.shapes.ttl", vocab_v2_shapes()),
|
|
]
|
|
}
|
|
|
|
fn sets_of(r: &Registration) -> Vec<&'static str> {
|
|
let mut s = Vec::new();
|
|
if r.floor { s.push("floor"); }
|
|
if r.recommended { s.push("recommended"); }
|
|
s
|
|
}
|
|
|
|
fn json_text(v: &serde_json::Value) -> String {
|
|
let mut s = serde_json::to_string_pretty(v).expect("serialize");
|
|
s.push('\n');
|
|
s
|
|
}
|
|
|
|
/// `wai/registry/capabilities.json`.
|
|
pub fn capabilities_json() -> String {
|
|
use serde_json::{json, Value};
|
|
let caps: Vec<Value> = registrations()
|
|
.iter()
|
|
.map(|r| {
|
|
let mut v = json!({
|
|
"capability": r.capability,
|
|
"kind": r.kind.label(),
|
|
"status": r.status.label(),
|
|
"media": r.media.map(Media::label),
|
|
"role": r.role,
|
|
"tier": r.tier.map(FidelityTier::label),
|
|
"licence": r.licence.map(LicenseClass::label),
|
|
"replicate": r.replicate.map(ReplicateClass::label),
|
|
"sets": sets_of(r),
|
|
"spec_section": r.spec_section,
|
|
"edition": r.edition,
|
|
"registered": r.registered,
|
|
});
|
|
if let Some(o) = r.ops {
|
|
v["ops"] = ops_json(&o);
|
|
}
|
|
v
|
|
})
|
|
.collect();
|
|
let mut ids: Vec<&Identifier> = IDENTIFIERS.iter().collect();
|
|
ids.sort_by_key(|i| i.identifier);
|
|
let ids: Vec<Value> = ids
|
|
.iter()
|
|
.map(|i| json!({ "identifier": i.identifier, "spec_section": i.spec_section, "meaning": i.meaning }))
|
|
.collect();
|
|
let mut labels: Vec<&UnregisteredLabel> = UNREGISTERED_LABELS.iter().collect();
|
|
labels.sort_by_key(|l| l.label);
|
|
let labels: Vec<Value> = labels.iter().map(|l| json!({ "label": l.label, "reason": l.reason })).collect();
|
|
let wires: Vec<Value> = sorted_wire_identifiers()
|
|
.iter()
|
|
.map(|w| json!({
|
|
"name": w.name,
|
|
"kind": w.kind.label(),
|
|
"document": w.document,
|
|
"section": w.section,
|
|
"status": w.status.label(),
|
|
}))
|
|
.collect();
|
|
json_text(&json!({
|
|
"schema": format!("{FORGE_TREE}/registry/capabilities.schema.json"),
|
|
"capabilities": caps,
|
|
"identifiers": ids,
|
|
"unregistered_labels": labels,
|
|
"wire_identifiers": wires,
|
|
}))
|
|
}
|
|
|
|
/// The registry's `ops` member (`extensions/integer-operators.md` §11), its members in
|
|
/// that section's order.
|
|
fn ops_json(o: &super::OpsMember) -> serde_json::Value {
|
|
use serde_json::{json, Map, Value};
|
|
let mut v = json!({ "set": "wai-ops/1" });
|
|
for (k, m) in [("profile", o.profile), ("subset", o.subset), ("lowering", o.lowering)] {
|
|
if let Some(m) = m {
|
|
v[k] = Value::from(m);
|
|
}
|
|
}
|
|
if !o.role_profiles.is_empty() {
|
|
v["role_profiles"] = Value::Object(o.role_profiles.iter().map(|(r, p)| (r.to_string(), Value::from(*p))).collect());
|
|
}
|
|
let mut stage = Map::new();
|
|
if let Some((table, escape, end)) = o.rans64 {
|
|
stage.insert("rans64".into(), json!({ "table": table, "escape": escape, "end": end }));
|
|
}
|
|
if let Some(b) = o.bucket {
|
|
stage.insert("bucket".into(), Value::from(b));
|
|
}
|
|
if !stage.is_empty() {
|
|
v["stage"] = Value::Object(stage);
|
|
}
|
|
v
|
|
}
|
|
|
|
fn nullable_enum(labels: &[&str]) -> serde_json::Value {
|
|
let mut e: Vec<serde_json::Value> = labels.iter().map(|l| serde_json::Value::from(*l)).collect();
|
|
e.push(serde_json::Value::Null);
|
|
serde_json::json!({ "enum": e })
|
|
}
|
|
|
|
/// The schema of a capability's `ops` member (`extensions/integer-operators.md` §11).
|
|
fn ops_schema() -> serde_json::Value {
|
|
serde_json::json!({
|
|
"type": "object",
|
|
"description": "The integer operator set the capability decodes through (extensions/integer-operators.md §11). Absent for a capability that does not. A capability whose decode runs no graph, only stage operators (§13.5), has no profile, subset or lowering.",
|
|
"additionalProperties": false,
|
|
"required": ["set"],
|
|
"dependentRequired": {
|
|
"profile": ["subset", "lowering"],
|
|
"subset": ["profile", "lowering"],
|
|
"lowering": ["profile", "subset"],
|
|
"role_profiles": ["profile"]
|
|
},
|
|
"anyOf": [{ "required": ["lowering"] }, { "required": ["stage"] }],
|
|
"properties": {
|
|
"set": { "const": "wai-ops/1" },
|
|
"profile": { "enum": ["acc32", "acc64"] },
|
|
"subset": { "enum": ["full", "npu"] },
|
|
"lowering": { "type": "string" },
|
|
"role_profiles": {
|
|
"type": "object",
|
|
"description": "Roles of the lowering whose graphs every conforming set holds to a stronger profile than `profile`, each with that profile (extensions/integer-operators.md §11).",
|
|
"minProperties": 1,
|
|
"additionalProperties": { "enum": ["acc32", "acc64"] }
|
|
},
|
|
"stage": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"rans64": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"required": ["table", "escape", "end"],
|
|
"properties": {
|
|
"table": { "enum": ["t4097", "t2"] },
|
|
"escape": { "enum": ["lenient", "strict"] },
|
|
"end": { "enum": ["canonical", "final_only"] }
|
|
}
|
|
},
|
|
"bucket": { "enum": ["ceil", "floor"] }
|
|
}
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
/// `wai/registry/capabilities.schema.json` (JSON Schema 2020-12). Its enums are
|
|
/// the registry's label sets.
|
|
pub fn capabilities_schema() -> String {
|
|
use serde_json::json;
|
|
let kinds: Vec<&str> = Kind::all().iter().map(|k| k.label()).collect();
|
|
let statuses: Vec<&str> = RegistrationStatus::all().iter().map(|s| s.label()).collect();
|
|
let media: Vec<&str> = Media::all().iter().map(|m| m.label()).collect();
|
|
let tiers: Vec<&str> = FidelityTier::all().iter().map(|t| t.label()).collect();
|
|
let licences: Vec<&str> = LicenseClass::all().iter().map(|l| l.label()).collect();
|
|
let replicates: Vec<&str> = ReplicateClass::all().iter().map(|r| r.label()).collect();
|
|
let wire_kinds: Vec<&str> = WireKind::all().iter().map(|k| k.label()).collect();
|
|
let wire_statuses: Vec<&str> = WireStatus::all().iter().map(|s| s.label()).collect();
|
|
let string_pattern = "^wai(\\.[a-z0-9_]+)+$";
|
|
json_text(&json!({
|
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
"$id": format!("{FORGE_TREE}/registry/capabilities.schema.json"),
|
|
"title": "WAI capability registry",
|
|
"description": "Every string SPEC §5 registers, generated by `wai registry export` from the reference implementation's registry (wai-rs/src/codecs/registry.rs). REGISTRY.md states the policy.",
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"required": ["schema", "capabilities", "identifiers", "unregistered_labels", "wire_identifiers"],
|
|
"properties": {
|
|
"schema": { "type": "string" },
|
|
"capabilities": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"required": ["capability", "kind", "status", "media", "role", "tier", "licence",
|
|
"replicate", "sets", "spec_section", "edition", "registered"],
|
|
"properties": {
|
|
"capability": { "type": "string", "pattern": string_pattern },
|
|
"kind": { "enum": kinds },
|
|
"status": { "enum": statuses },
|
|
"media": nullable_enum(&media),
|
|
"role": nullable_enum(&ROLE_LABELS),
|
|
"tier": nullable_enum(&tiers),
|
|
"licence": nullable_enum(&licences),
|
|
"replicate": nullable_enum(&replicates),
|
|
"sets": { "type": "array", "uniqueItems": true, "items": { "enum": ["floor", "recommended"] } },
|
|
"spec_section": { "type": "string" },
|
|
"edition": {
|
|
"type": ["string", "null"],
|
|
"description": "The edition the registration names; null means the edition of the named standard current on the date in `registered` (SPEC §8)."
|
|
},
|
|
"registered": {
|
|
"type": "string",
|
|
"pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$",
|
|
"description": "The date of the first commit of this repository that registers the string; the specification entered the repository on 2026-06-12."
|
|
},
|
|
"ops": ops_schema()
|
|
}
|
|
}
|
|
},
|
|
"identifiers": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"required": ["identifier", "spec_section", "meaning"],
|
|
"properties": {
|
|
"identifier": { "type": "string", "pattern": string_pattern },
|
|
"spec_section": { "type": "string" },
|
|
"meaning": { "type": "string" }
|
|
}
|
|
}
|
|
},
|
|
"unregistered_labels": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"required": ["label", "reason"],
|
|
"properties": {
|
|
"label": { "type": "string", "pattern": string_pattern },
|
|
"reason": { "type": "string" }
|
|
}
|
|
}
|
|
},
|
|
"wire_identifiers": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"required": ["name", "kind", "document", "section", "status"],
|
|
"properties": {
|
|
"name": { "type": "string" },
|
|
"kind": { "enum": wire_kinds },
|
|
"document": { "type": "string" },
|
|
"section": { "type": "string", "pattern": "^(§[0-9]+(\\.[0-9]+)*|Appendix [A-Z])$" },
|
|
"status": { "enum": wire_statuses }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}))
|
|
}
|
|
|
|
/// A Turtle string literal.
|
|
fn ttl_str(s: &str) -> String {
|
|
let mut o = String::from("\"");
|
|
for c in s.chars() {
|
|
match c {
|
|
'"' => o.push_str("\\\""),
|
|
'\\' => o.push_str("\\\\"),
|
|
'\n' => o.push_str("\\n"),
|
|
_ => o.push(c),
|
|
}
|
|
}
|
|
o.push('"');
|
|
o
|
|
}
|
|
|
|
const TTL_PREFIXES: &str = "@prefix wai: <https://wai.transaction.science/vocab/v2#> .\n\
|
|
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .\n\
|
|
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .\n\
|
|
@prefix owl: <http://www.w3.org/2002/07/owl#> .\n\
|
|
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .\n\
|
|
@prefix dc: <http://purl.org/dc/terms/> .\n";
|
|
|
|
/// The local name of an enumeration individual of v2: its class's prefix and its
|
|
/// label (`kind-companion`, `role-companion`, `status-registered`, …), so that no
|
|
/// two enumerations, and no enumeration and property, share an IRI.
|
|
fn individual(prefix: &str, label: &str) -> String {
|
|
format!("{prefix}-{label}")
|
|
}
|
|
|
|
/// The enumerations of v2: `(class, individual prefix, labels)`.
|
|
fn enumerations() -> [(&'static str, &'static str, Vec<&'static str>); 7] {
|
|
[
|
|
("Kind", "kind", Kind::all().iter().map(|k| k.label()).collect()),
|
|
("Status", "status", RegistrationStatus::all().iter().map(|s| s.label()).collect()),
|
|
("Media", "media", Media::all().iter().map(|m| m.label()).collect()),
|
|
("Role", "role", ROLE_LABELS.to_vec()),
|
|
("Tier", "tier", FidelityTier::all().iter().map(|t| t.label()).collect()),
|
|
("Licence", "licence", LicenseClass::all().iter().map(|l| l.label()).collect()),
|
|
("ReplicateClass", "replicate", ReplicateClass::all().iter().map(|r| r.label()).collect()),
|
|
]
|
|
}
|
|
|
|
/// The registered tier tokens of a pin (SPEC §3.1), from [`TIER_TOKENS`].
|
|
fn tier_tokens() -> Vec<&'static str> {
|
|
TIER_TOKENS.iter().map(|&(t, _)| t).collect()
|
|
}
|
|
|
|
/// The parameter-set pin's terms (SPEC §3.1), as v1 states them. `pinSha256` and
|
|
/// `pinForm` name no domain: they are also the members of a pin's `supersedes`
|
|
/// object, which is not itself a pin.
|
|
const PIN_TERMS_TTL: &str = "# ─── The parameter-set pin (SPEC section 3.1) ────────────────────────\n\n\
|
|
wai:prior a owl:ObjectProperty ; rdfs:range wai:ParameterSetPin ; rdfs:label \"Parameter-set pin (conditioning.prior, or a component's prior)\" .\n\
|
|
wai:pinId a owl:DatatypeProperty ; rdfs:domain wai:ParameterSetPin ; rdfs:range xsd:string ; rdfs:label \"Pin name (informative)\" .\n\
|
|
wai:pinSha256 a owl:DatatypeProperty ; rdfs:range xsd:string ; rdfs:label \"SHA-256 of the parameter set in its form (64 lowercase hex)\" ;\n rdfs:comment \"A member of a pin and of its supersedes object.\" .\n\
|
|
wai:pinDeterminism a owl:DatatypeProperty ; rdfs:domain wai:ParameterSetPin ; rdfs:range xsd:string ; rdfs:label \"How the decode is made reproducible\" .\n\
|
|
wai:pinForm a owl:DatatypeProperty ; rdfs:range xsd:string ; rdfs:label \"Registered prior form\" ;\n rdfs:comment \"A member of a pin and of its supersedes object.\" .\n\
|
|
wai:pinSupersedes a owl:ObjectProperty ; rdfs:domain wai:ParameterSetPin ; rdfs:label \"The parameter set this one replaces (informative)\" ;\n rdfs:comment \"Names that set by pinSha256 and, if it is pinned in a declared form, pinForm; it is not itself a pin.\" .\n";
|
|
|
|
/// The SHACL shapes of the parameter-set pin (SPEC §3.1), the same in v1 and v2:
|
|
/// the JSON-LD context types no `prior` object, so the pin shape targets whatever
|
|
/// `wai:prior` points at; `pinTier` is the closed list [`TIER_TOKENS`] holds; and
|
|
/// `supersedes` names a set by its digest and, optionally, its form.
|
|
fn pin_shapes() -> String {
|
|
let tiers: Vec<String> = tier_tokens().iter().map(|t| format!("\"{t}\"")).collect();
|
|
let mut o = String::new();
|
|
o.push_str("# The parameter-set pin (SPEC section 3.1). The JSON-LD context types no prior object,\n");
|
|
o.push_str("# so the shape targets whatever wai:prior points at rather than a class. pinTier is a\n");
|
|
o.push_str("# closed vocabulary; the tokens are the ones codecs::TIER_TOKENS holds.\n");
|
|
o.push_str("wai:ParameterSetPinShape a sh:NodeShape ;\n");
|
|
o.push_str(" sh:targetObjectsOf wai:prior ;\n");
|
|
o.push_str(" sh:property [ sh:path wai:pinId ; sh:datatype xsd:string ; sh:minCount 1 ; sh:maxCount 1 ] ;\n");
|
|
o.push_str(" sh:property [ sh:path wai:pinSha256 ; sh:datatype xsd:string ; sh:minCount 1 ; sh:maxCount 1 ;\n");
|
|
o.push_str(" sh:pattern \"^[a-f0-9]{64}$\" ] ;\n");
|
|
o.push_str(" sh:property [ sh:path wai:pinDeterminism ; sh:datatype xsd:string ; sh:minCount 1 ; sh:maxCount 1 ] ;\n");
|
|
o.push_str(" sh:property [ sh:path wai:pinForm ; sh:datatype xsd:string ; sh:maxCount 1 ] ;\n");
|
|
o.push_str(&format!(" sh:property [ sh:path wai:pinTier ; sh:datatype xsd:string ; sh:maxCount 1 ;\n sh:in ( {} ) ] ;\n", tiers.join(" ")));
|
|
o.push_str(" sh:property [ sh:path wai:pinSupersedes ; sh:node wai:SupersedesShape ; sh:maxCount 1 ] .\n\n");
|
|
o.push_str("# supersedes names a set as a pin names one, by sha256 and, if it is pinned in a\n");
|
|
o.push_str("# declared form, form; it has no id, determinism or tier.\n");
|
|
o.push_str("wai:SupersedesShape a sh:NodeShape ;\n");
|
|
o.push_str(" sh:property [ sh:path wai:pinSha256 ; sh:datatype xsd:string ; sh:minCount 1 ; sh:maxCount 1 ;\n");
|
|
o.push_str(" sh:pattern \"^[a-f0-9]{64}$\" ] ;\n");
|
|
o.push_str(" sh:property [ sh:path wai:pinForm ; sh:datatype xsd:string ; sh:maxCount 1 ] .\n");
|
|
o
|
|
}
|
|
|
|
/// `wai/vocab/v2.ttl`: one IRI per registered string, with its registry properties
|
|
/// as enumeration individuals, and the manifest terms the JSON-LD context maps.
|
|
pub fn vocab_v2_ttl() -> String {
|
|
let mut o = String::new();
|
|
o.push_str("# Generated by `wai registry export` from wai-rs/src/codecs/registry.rs. Do not edit.\n");
|
|
o.push_str(TTL_PREFIXES);
|
|
o.push_str("@prefix sh: <http://www.w3.org/ns/shacl#> .\n\n");
|
|
o.push_str("<https://wai.transaction.science/vocab/v2> a owl:Ontology ;\n");
|
|
o.push_str(" dc:title \"WAI vocabulary (v2)\" ;\n");
|
|
o.push_str(" dc:description \"The WAI capability registry as RDF: one IRI per string SPEC section 5 registers, with its kind, status, media class, role, fidelity tier, licence class and replicate class; and the manifest terms of the v2 JSON-LD context. Generated from the reference implementation's registry.\" ;\n");
|
|
o.push_str(" dc:license <https://www.apache.org/licenses/LICENSE-2.0> ;\n");
|
|
o.push_str(" owl:versionInfo \"2\" .\n\n");
|
|
|
|
o.push_str("# ─── Classes ─────────────────────────────────────────────────────────\n\n");
|
|
for (class, label) in [
|
|
("Manifest", "WAI manifest"),
|
|
("Component", "WAI2 component (an entry of a manifest's renditions)"),
|
|
("Capability", "Registered string"),
|
|
("Kind", "Kind of registered string"),
|
|
("Status", "Registration status"),
|
|
("Media", "Media class"),
|
|
("Role", "Dispatch role"),
|
|
("Tier", "Fidelity tier"),
|
|
("Licence", "Licence class"),
|
|
("ReplicateClass", "Replicate class"),
|
|
("ParameterSetPin", "Parameter-set pin (SPEC section 3.1)"),
|
|
] {
|
|
o.push_str(&format!("wai:{class} a owl:Class ; rdfs:label {} .\n", ttl_str(label)));
|
|
}
|
|
o.push('\n');
|
|
o.push_str("# ─── Enumerations (individuals named <class prefix>-<label>) ─────────\n\n");
|
|
for (class, prefix, labels) in &enumerations() {
|
|
for l in labels {
|
|
o.push_str(&format!("wai:{} a wai:{class} ; rdfs:label {} .\n", individual(prefix, l), ttl_str(l)));
|
|
}
|
|
}
|
|
o.push('\n');
|
|
o.push_str("# ─── Properties ──────────────────────────────────────────────────────\n\n");
|
|
for (p, range, label) in [
|
|
("capability", "wai:Capability", "Capability (model_requirement.capability, or a component's capability)"),
|
|
("fallback", "wai:Capability", "Fallback capability (model_requirement.fallback)"),
|
|
("companionOf", "wai:Capability", "Base capability a companion component is applied with (companion_of)"),
|
|
("renditions", "wai:Component", "WAI2 component"),
|
|
("media", "wai:Media", "Media class (informational in a manifest)"),
|
|
("kind", "wai:Kind", "Kind of registered string"),
|
|
("status", "wai:Status", "Registration status"),
|
|
("role", "wai:Role", "Dispatch role"),
|
|
("tier", "wai:Tier", "Fidelity tier"),
|
|
("licence", "wai:Licence", "Licence class"),
|
|
("replicateClass", "wai:ReplicateClass", "Replicate class"),
|
|
] {
|
|
o.push_str(&format!("wai:{p} a owl:ObjectProperty ; rdfs:range {range} ; rdfs:label {} .\n", ttl_str(label)));
|
|
}
|
|
for (p, domain, range, label) in [
|
|
("wai", "wai:Manifest", "xsd:string", "WAI version (the manifest's wai field)"),
|
|
("intent", "wai:Manifest", "xsd:string", "Intent"),
|
|
("payloadKind", "", "xsd:string", "Payload kind (conditioning.kind, or a component's kind)"),
|
|
("componentRole", "wai:Component", "xsd:string", "Component role (a component's role)"),
|
|
("target", "wai:Manifest", "rdf:JSON", "Target (carried as a JSON literal)"),
|
|
("specSection", "wai:Capability", "xsd:string", "Registering section of SPEC"),
|
|
("edition", "wai:Capability", "xsd:string", "Edition the registration names"),
|
|
("registeredOn", "wai:Capability", "xsd:date", "Date registered"),
|
|
] {
|
|
let domain = if domain.is_empty() { String::new() } else { format!(" rdfs:domain {domain} ;") };
|
|
o.push_str(&format!("wai:{p} a owl:DatatypeProperty ;{domain} rdfs:range {range} ; rdfs:label {} .\n", ttl_str(label)));
|
|
}
|
|
o.push('\n');
|
|
o.push_str(PIN_TERMS_TTL);
|
|
o.push_str(&format!("wai:pinTier a owl:DatatypeProperty ; rdfs:domain wai:ParameterSetPin ; rdfs:range xsd:string ; rdfs:label \"Declared reproducibility tier\" ;\n rdfs:comment {} .\n",
|
|
ttl_str(&format!("A closed vocabulary: {}.", tier_tokens().join(", ")))));
|
|
o.push('\n');
|
|
o.push_str("# ─── Registered strings ──────────────────────────────────────────────\n");
|
|
for r in registrations() {
|
|
o.push('\n');
|
|
o.push_str(&format!("wai:{} a wai:Capability ;\n", r.capability));
|
|
o.push_str(&format!(" rdfs:label {} ;\n", ttl_str(r.capability)));
|
|
o.push_str(&format!(" wai:kind wai:{} ;\n", individual("kind", r.kind.label())));
|
|
o.push_str(&format!(" wai:status wai:{} ;\n", individual("status", r.status.label())));
|
|
if let Some(m) = r.media { o.push_str(&format!(" wai:media wai:{} ;\n", individual("media", m.label()))); }
|
|
if let Some(role) = r.role { o.push_str(&format!(" wai:role wai:{} ;\n", individual("role", role))); }
|
|
if let Some(t) = r.tier { o.push_str(&format!(" wai:tier wai:{} ;\n", individual("tier", t.label()))); }
|
|
if let Some(l) = r.licence { o.push_str(&format!(" wai:licence wai:{} ;\n", individual("licence", l.label()))); }
|
|
if let Some(c) = r.replicate { o.push_str(&format!(" wai:replicateClass wai:{} ;\n", individual("replicate", c.label()))); }
|
|
if let Some(e) = r.edition { o.push_str(&format!(" wai:edition {} ;\n", ttl_str(e))); }
|
|
o.push_str(&format!(" wai:specSection {} ;\n", ttl_str(r.spec_section)));
|
|
o.push_str(&format!(" wai:registeredOn {}^^xsd:date .\n", ttl_str(r.registered)));
|
|
}
|
|
o
|
|
}
|
|
|
|
/// The registered strings a manifest may name as its `capability`: payload,
|
|
/// companion and refinement capabilities whose status is registered (a candidate
|
|
/// MUST NOT be emitted). A `WAI1` `fallback` additionally excludes the companions
|
|
/// and the refinements.
|
|
fn emittable() -> Vec<Registration> {
|
|
registrations()
|
|
.into_iter()
|
|
.filter(|r| matches!(r.kind, Kind::Payload | Kind::Companion | Kind::Refinement) && r.status == RegistrationStatus::Registered)
|
|
.collect()
|
|
}
|
|
|
|
/// `wai/vocab/v2.shapes.ttl` (SHACL Core): the capabilities a manifest names,
|
|
/// against the registry. A manifest needs no `@type` to be checked: the shape
|
|
/// targets every node with a `wai` (version) or an `intent` field (every WAI
|
|
/// manifest has both) and every component of a `renditions` list. `media` is informational and a reader MUST
|
|
/// accept a value it does not know (SPEC §3, §8), so the shape does not restrict
|
|
/// its value.
|
|
pub fn vocab_v2_shapes() -> String {
|
|
let caps: Vec<String> = emittable().iter().map(|r| format!("wai:{}", r.capability)).collect();
|
|
let payloads: Vec<String> = emittable()
|
|
.iter()
|
|
.filter(|r| r.kind == Kind::Payload)
|
|
.map(|r| format!("wai:{}", r.capability))
|
|
.collect();
|
|
let list = |v: &[String]| {
|
|
let mut s = String::from("(");
|
|
for x in v {
|
|
s.push_str("\n ");
|
|
s.push_str(x);
|
|
}
|
|
s.push_str("\n )");
|
|
s
|
|
};
|
|
let mut o = String::new();
|
|
o.push_str("# Generated by `wai registry export` from wai-rs/src/codecs/registry.rs. Do not edit.\n");
|
|
o.push_str("@prefix wai: <https://wai.transaction.science/vocab/v2#> .\n");
|
|
o.push_str("@prefix sh: <http://www.w3.org/ns/shacl#> .\n");
|
|
o.push_str("@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .\n\n");
|
|
o.push_str("# A WAI manifest, typed or not: every manifest has a wai (version) field. A WAI1 manifest names a\n");
|
|
o.push_str("# capability, a WAI2 manifest a renditions list, and never both. The capability is a\n");
|
|
o.push_str("# registered payload, companion or refinement capability that is not a candidate; the\n");
|
|
o.push_str("# fallback a registered payload capability that is not a candidate. (A WAI1 naming a\n");
|
|
o.push_str("# companion-only capability, or a refinement-only one without refines, parses but does\n");
|
|
o.push_str("# not conform; the reference implementation's role check reports it.) media is\n");
|
|
o.push_str("# informational, and a reader accepts a value it does not know\n");
|
|
o.push_str("# (SPEC sections 3 and 8), so only its form is checked.\n");
|
|
o.push_str("wai:ManifestShape a sh:NodeShape ;\n");
|
|
o.push_str(" sh:targetClass wai:Manifest ;\n");
|
|
o.push_str(" sh:targetSubjectsOf wai:wai ;\n");
|
|
o.push_str(" sh:targetSubjectsOf wai:intent ;\n");
|
|
o.push_str(&format!(" sh:property [ sh:path wai:capability ; sh:nodeKind sh:IRI ; sh:maxCount 1 ;\n sh:in {} ] ;\n", list(&caps)));
|
|
o.push_str(&format!(" sh:property [ sh:path wai:fallback ; sh:nodeKind sh:IRI ; sh:maxCount 1 ;\n sh:in {} ] ;\n", list(&payloads)));
|
|
o.push_str(" sh:property [ sh:path wai:media ; sh:nodeKind sh:IRI ; sh:maxCount 1 ] ;\n");
|
|
o.push_str(" sh:property [ sh:path wai:intent ; sh:datatype xsd:string ; sh:minCount 1 ; sh:maxCount 1 ] ;\n");
|
|
o.push_str(" sh:xone (\n [ sh:property [ sh:path wai:capability ; sh:minCount 1 ] ]\n [ sh:property [ sh:path wai:renditions ; sh:minCount 1 ] ]\n ) .\n\n");
|
|
o.push_str("# A WAI2 component, in any role: its capability is a registered payload, companion or\n");
|
|
o.push_str("# refinement capability that is not a candidate, and the base a companion names is a\n");
|
|
o.push_str("# registered payload capability that is not a candidate.\n");
|
|
o.push_str("wai:ComponentShape a sh:NodeShape ;\n");
|
|
o.push_str(" sh:targetClass wai:Component ;\n");
|
|
o.push_str(" sh:targetObjectsOf wai:renditions ;\n");
|
|
o.push_str(&format!(" sh:property [ sh:path wai:capability ; sh:nodeKind sh:IRI ; sh:minCount 1 ; sh:maxCount 1 ;\n sh:in {} ] ;\n", list(&caps)));
|
|
o.push_str(&format!(" sh:property [ sh:path wai:companionOf ; sh:nodeKind sh:IRI ; sh:maxCount 1 ;\n sh:in {} ] .\n\n", list(&payloads)));
|
|
o.push_str(&pin_shapes());
|
|
o
|
|
}
|
|
|
|
/// `wai/vocab/v2.jsonld`: a JSON-LD context for WAI manifests, `WAI1` and `WAI2`.
|
|
/// Under it a manifest's `capability`, `fallback` and a component's `capability`
|
|
/// and `companion_of` expand to the v2 capability IRIs, and `media` to a media-class
|
|
/// individual; `kind` (of the conditioning, or of a component) and a component's
|
|
/// `role` are plain strings with terms of their own, distinct from the registry's
|
|
/// kind and role; `target` is carried as a JSON literal.
|
|
pub fn vocab_v2_jsonld() -> String {
|
|
use serde_json::json;
|
|
// No `wai` prefix term: a WAI manifest has a top-level `wai` (version) key,
|
|
// which under `@vocab` expands to the namespace's own `wai` property.
|
|
let t = |local: &str| format!("{VOCAB_V2_NS}{local}");
|
|
json_text(&json!({
|
|
"@context": {
|
|
"@version": 1.1,
|
|
"@vocab": VOCAB_V2_NS,
|
|
"xsd": "http://www.w3.org/2001/XMLSchema#",
|
|
"Manifest": t("Manifest"),
|
|
"Component": t("Component"),
|
|
"model_requirement": "@nest",
|
|
"capability": { "@id": t("capability"), "@type": "@vocab" },
|
|
"fallback": { "@id": t("fallback"), "@type": "@vocab" },
|
|
"companion_of": { "@id": t("companionOf"), "@type": "@vocab" },
|
|
"media": { "@id": t("media"), "@type": "@vocab", "@context": { "@vocab": t("media-") } },
|
|
"intent": { "@id": t("intent"), "@type": "xsd:string" },
|
|
"kind": { "@id": t("payloadKind"), "@type": "xsd:string" },
|
|
"role": { "@id": t("componentRole"), "@type": "xsd:string" },
|
|
"renditions": { "@id": t("renditions") },
|
|
"target": { "@id": t("target"), "@type": "@json" },
|
|
"ParameterSetPin": t("ParameterSetPin"),
|
|
// The pin (SPEC §3.1), as `conditioning.prior` or a component's `prior`:
|
|
// its members under the manifest's own names. The scoped context reaches
|
|
// the `supersedes` object too. `tier` is an untyped string so that a
|
|
// SHACL validator compares it with the shape's tier list.
|
|
"prior": { "@id": t("prior"), "@context": {
|
|
"id": { "@id": t("pinId"), "@type": "xsd:string" },
|
|
"sha256": { "@id": t("pinSha256"), "@type": "xsd:string" },
|
|
"determinism": { "@id": t("pinDeterminism"), "@type": "xsd:string" },
|
|
"form": { "@id": t("pinForm"), "@type": "xsd:string" },
|
|
"tier": { "@id": t("pinTier") },
|
|
"supersedes": { "@id": t("pinSupersedes") }
|
|
} }
|
|
}
|
|
}))
|
|
}
|
|
|
|
/// The generated table of `wai/REGISTRY.md` (the text between
|
|
/// [`REGISTRY_MD_BEGIN`] and [`REGISTRY_MD_END`], exclusive).
|
|
pub fn registry_md_table() -> String {
|
|
let dash = |o: Option<&str>| o.unwrap_or("—").to_string();
|
|
let mut o = String::new();
|
|
o.push_str("| string | kind | status | media | role | licence | replicate | sets | registered in |\n");
|
|
o.push_str("|---|---|---|---|---|---|---|---|---|\n");
|
|
for r in registrations() {
|
|
let sets = sets_of(&r);
|
|
o.push_str(&format!(
|
|
"| `{}` | {} | {} | {} | {} | {} | {} | {} | {} |\n",
|
|
r.capability,
|
|
r.kind.label(),
|
|
r.status.label(),
|
|
dash(r.media.map(Media::label)),
|
|
dash(r.role),
|
|
dash(r.licence.map(LicenseClass::label)),
|
|
dash(r.replicate.map(ReplicateClass::label)),
|
|
if sets.is_empty() { "—".to_string() } else { sets.join(", ") },
|
|
r.spec_section,
|
|
));
|
|
}
|
|
o.push('\n');
|
|
o.push_str("| identifier (not a capability) | meaning | in |\n|---|---|---|\n");
|
|
for i in IDENTIFIERS {
|
|
o.push_str(&format!("| `{}` | {} | {} |\n", i.identifier, i.meaning, i.spec_section));
|
|
}
|
|
o.push('\n');
|
|
o.push_str("| unregistered label | reason |\n|---|---|\n");
|
|
for l in UNREGISTERED_LABELS {
|
|
o.push_str(&format!("| `{}` | {} |\n", l.label, l.reason));
|
|
}
|
|
o.push('\n');
|
|
o.push_str("| wire identifier (not a capability) | kind | status | defined in |\n|---|---|---|---|\n");
|
|
for w in sorted_wire_identifiers() {
|
|
let doc = w.document.trim_end_matches(".md").trim_start_matches("extensions/");
|
|
o.push_str(&format!("| `{}` | {} | {} | {} {} |\n", w.name, w.kind.label(), w.status.label(), doc, w.section));
|
|
}
|
|
o
|
|
}
|
|
|
|
/// [`WIRE_IDENTIFIERS`] sorted by name, then kind: the order the export writes.
|
|
pub fn sorted_wire_identifiers() -> Vec<&'static WireIdentifier> {
|
|
let mut v: Vec<&WireIdentifier> = WIRE_IDENTIFIERS.iter().collect();
|
|
v.sort_by(|a, b| a.name.cmp(b.name).then(a.kind.cmp(&b.kind)));
|
|
v
|
|
}
|
|
|
|
/// `md` with the text between its [`REGISTRY_MD_BEGIN`] and [`REGISTRY_MD_END`]
|
|
/// lines replaced by [`registry_md_table`], or `None` if the markers are missing.
|
|
pub fn splice_registry_md(md: &str) -> Option<String> {
|
|
let b = md.find(REGISTRY_MD_BEGIN)? + REGISTRY_MD_BEGIN.len();
|
|
let e = md[b..].find(REGISTRY_MD_END)? + b;
|
|
Some(format!("{}\n{}{}", &md[..b], registry_md_table(), &md[e..]))
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
use std::path::PathBuf;
|
|
|
|
fn wai_dir() -> PathBuf {
|
|
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("..")
|
|
}
|
|
|
|
fn read(rel: &str) -> String {
|
|
let p = wai_dir().join(rel);
|
|
std::fs::read_to_string(&p).unwrap_or_else(|e| panic!("read {}: {e}", p.display()))
|
|
}
|
|
|
|
#[test]
|
|
fn the_table_covers_every_registered_string_once() {
|
|
let rows: Vec<&str> = ROWS.iter().map(|r| r.0).collect();
|
|
let mut sorted = rows.clone();
|
|
sorted.sort_unstable();
|
|
sorted.dedup();
|
|
assert_eq!(sorted.len(), rows.len(), "a string has two rows");
|
|
// Every payload and companion capability has a row, and every row is one
|
|
// of those or a record.
|
|
for &c in known_capabilities() {
|
|
assert!(rows.contains(&c), "{c} is registered but has no row");
|
|
}
|
|
for &c in &rows {
|
|
assert!(is_known_capability(c) || RECORDS.contains(&c), "{c} has a row but is not registered");
|
|
}
|
|
for &c in RECORDS {
|
|
assert!(rows.contains(&c), "record {c} has no row");
|
|
assert!(!is_known_capability(c), "record {c} must not be a dispatchable capability");
|
|
assert_eq!(capability_kind(c), Some(Kind::Record));
|
|
}
|
|
// Derivations are registered through the derivation table.
|
|
for op in derivation::derivation_operations() {
|
|
assert_eq!(capability_kind(op.capability), Some(Kind::Derivation));
|
|
assert!(!rows.contains(&op.capability));
|
|
}
|
|
// Identifiers and unregistered labels are not registered strings.
|
|
for i in IDENTIFIERS {
|
|
assert_eq!(capability_kind(i.identifier), None, "{}", i.identifier);
|
|
}
|
|
for l in UNREGISTERED_LABELS {
|
|
assert_eq!(capability_kind(l.label), None, "{}", l.label);
|
|
}
|
|
for r in registrations() {
|
|
assert!(r.registered.len() == 10 && r.registered.as_bytes()[4] == b'-', "{}", r.capability);
|
|
assert!(r.registered >= "2026-06-12", "{}: before the specification entered the repository", r.capability);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn candidates_are_the_registrations_with_no_pinned_payload() {
|
|
let mut c: Vec<&str> = known_capabilities().iter().copied().filter(|c| is_candidate(c)).collect();
|
|
c.sort_unstable();
|
|
assert_eq!(c, vec![CAP_IMAGE_IEEE1857_11, CAP_SPLAT_SOG, CAP_TENSOR_NNC]);
|
|
for &cap in &c {
|
|
assert!(!mandatory_floor().contains(&cap) && !recommended_set().contains(&cap));
|
|
assert!(!sink_capabilities().contains(&cap));
|
|
assert!(!is_companion_only(cap));
|
|
assert!(!is_dispatchable(cap));
|
|
}
|
|
assert!(!is_candidate("wai.image.nope"));
|
|
assert_eq!(capability_status("wai.image.nope"), None);
|
|
// Among registered payload, companion and refinement capabilities,
|
|
// dispatchable is exactly: not companion-only, not refinement-only, not a
|
|
// candidate.
|
|
for &cap in known_capabilities() {
|
|
assert_eq!(is_dispatchable(cap), !is_companion_only(cap) && !is_refinement_only(cap) && !is_candidate(cap), "{cap}");
|
|
}
|
|
// Records and derivations name no payload format: never dispatched.
|
|
for &cap in RECORDS {
|
|
assert!(!is_dispatchable(cap), "{cap}");
|
|
}
|
|
assert!(!is_dispatchable(derivation::CAP_DERIVE_CROP));
|
|
// A string this revision does not register is left to the sink (SPEC §4,
|
|
// §8): a later MINOR revision may register it.
|
|
assert!(is_dispatchable("wai.image.nope"));
|
|
}
|
|
|
|
#[test]
|
|
fn licence_labels_are_the_spec_vocabulary() {
|
|
let l: Vec<&str> = LicenseClass::all().iter().map(|c| c.label()).collect();
|
|
assert_eq!(l, ["royalty-free", "patent-pool", "proprietary", "non-commercial"]);
|
|
}
|
|
|
|
#[test]
|
|
fn every_payload_and_companion_capability_has_a_media_class() {
|
|
for &c in known_capabilities() {
|
|
let m = capability_media(c).unwrap_or_else(|| panic!("{c} has no media class"));
|
|
// The video media class of §7.1 rule 2 is the video media here.
|
|
if is_video_class(c) {
|
|
assert_eq!(m, Media::Video, "{c}");
|
|
}
|
|
if is_companion_only(c) && c.starts_with("wai.meta.") {
|
|
assert_eq!(m, Media::Metadata, "{c}");
|
|
}
|
|
}
|
|
assert_eq!(capability_media(CAP_NEURAL_BMSHJ2018), Some(Media::Image));
|
|
assert_eq!(capability_media(CAP_SPLAT_SPZ), Some(Media::Volumetric));
|
|
assert_eq!(capability_media(CAP_VIDEO_MANIFEST), None);
|
|
assert_eq!(capability_media("wai.image.nope"), None);
|
|
}
|
|
|
|
/// The committed export is what this module renders, byte for byte. Fails on
|
|
/// a registry change that was not exported, and on a hand edit of an export.
|
|
/// Regenerate with `cargo run --no-default-features --bin wai -- registry export`.
|
|
#[test]
|
|
fn registry_export_matches_committed() {
|
|
for (rel, want) in export_files() {
|
|
assert!(read(rel) == want,
|
|
"wai/{rel} differs from the registry: run `cargo run --no-default-features --bin wai -- registry export` from wai/wai-rs");
|
|
}
|
|
let md = read("REGISTRY.md");
|
|
let want = splice_registry_md(&md).expect("REGISTRY.md has the generated markers");
|
|
assert!(md == want, "the generated table in wai/REGISTRY.md differs from the registry: run `wai registry export`");
|
|
}
|
|
|
|
/// The `ops` members (`extensions/integer-operators.md` §11). A `NeuralIntegerExact`
|
|
/// capability that carries one is at `acc64` with the full subset and names a
|
|
/// lowering of §13, and the export writes exactly these. In this revision
|
|
/// `wai.neural.int_synth`, `wai.splat.int_codec`, `wai.audio.int_codec`,
|
|
/// `wai.neural.int_hyper`, `wai.video.int_hyper`, `wai.neural.int_mlicpp` and
|
|
/// `wai.audio.opus.dred.int` decode through the operator set.
|
|
///
|
|
/// `wai.avatar.face`, `GenerativeDeterministic`, generates its frames through it
|
|
/// (`face-int/1`, extensions/avatars.md §7.6), at `acc64`.
|
|
///
|
|
/// `wai.image.jpegai` carries one for its scale path and entropy decodes, at `acc32`
|
|
/// (§13.6.1).
|
|
///
|
|
/// `wai.video.int_motion` and the four `int_refine` capabilities, `StandardDefined`,
|
|
/// decode through its stage operators only (§13.5): no graph, so no profile, subset
|
|
/// or lowering, and E1's modes.
|
|
///
|
|
/// `wai.world.model` carries none. Its integer renderer renders through the operator
|
|
/// set too, lowered by `world/1`, but that lowering is informative (§13.5): the
|
|
/// capability's registered payload is its signed action trace, whose decode is the
|
|
/// replay, and no payload text yet binds a trace to a renderer's set.
|
|
#[test]
|
|
fn ops_members_name_the_operator_set_a_capability_decodes_through() {
|
|
const STAGE_ONLY: [&str; 5] = [CAP_VIDEO_INT_MOTION, CAP_IMAGE_INT_REFINE, CAP_VIDEO_INT_REFINE, CAP_AUDIO_INT_REFINE, CAP_SPLAT_INT_REFINE];
|
|
let regs = registrations();
|
|
let mut with: Vec<&str> = regs.iter().filter(|r| r.ops.is_some()).map(|r| r.capability).collect();
|
|
with.sort_unstable();
|
|
let mut want = vec![CAP_AUDIO_INT_CODEC, CAP_AUDIO_OPUS_DRED_INT, CAP_AVATAR_FACE, CAP_IMAGE_JPEGAI, CAP_NEURAL_INT_HYPER, CAP_NEURAL_INT_MLICPP, CAP_NEURAL_INT_SYNTH, CAP_SPLAT_INT_CODEC, CAP_VIDEO_INT_HYPER];
|
|
want.extend(STAGE_ONLY);
|
|
want.sort_unstable();
|
|
assert_eq!(with, want);
|
|
let world = regs.iter().find(|r| r.capability == CAP_WORLD_MODEL).expect("wai.world.model is registered");
|
|
assert!(world.ops.is_none() && world.replicate != Some(ReplicateClass::NeuralIntegerExact), "wai.world.model: its decode is the trace's replay; its renderer's lowering is informative");
|
|
for r in regs.iter().filter(|r| r.ops.is_some()) {
|
|
let o = r.ops.unwrap();
|
|
if STAGE_ONLY.contains(&r.capability) {
|
|
// No graph: the stage operators of §13.5, with E1's payload modes.
|
|
assert_eq!(r.replicate, Some(ReplicateClass::StandardDefined), "{}", r.capability);
|
|
assert_eq!((o.profile, o.subset, o.lowering, o.bucket), (None, None, None, None), "{}", r.capability);
|
|
assert_eq!(o.rans64, Some(("t4097", "lenient", "canonical")), "{}", r.capability);
|
|
continue;
|
|
}
|
|
// JPEG AI's integer stages decode through the operator set at acc64, its scale
|
|
// path, which its entropy-consistency claim covers, at acc32 (§13.6).
|
|
let (class, profile) = match r.capability {
|
|
CAP_IMAGE_JPEGAI => (ReplicateClass::NeuralEntropyExact, "acc64"),
|
|
CAP_AVATAR_FACE => (ReplicateClass::GenerativeDeterministic, "acc64"),
|
|
_ => (ReplicateClass::NeuralIntegerExact, "acc64"),
|
|
};
|
|
assert_eq!(r.replicate, Some(class), "{}", r.capability);
|
|
let roles: &[(&str, &str)] = if r.capability == CAP_IMAGE_JPEGAI { &[("hs_y", "acc32"), ("hs_uv", "acc32")] } else { &[] };
|
|
assert_eq!(o.role_profiles, roles, "{}", r.capability);
|
|
assert_eq!((o.profile, o.subset), (Some(profile), Some("full")), "{}", r.capability);
|
|
assert!(o.lowering.is_some_and(|l| ["int_synth/1", "whm1/1", "wam1/1", "wmb1/1", "world/1", "jpegai-int/1", "dred-int/1", "face-int/1"].contains(&l)), "{}", r.capability);
|
|
}
|
|
let export: serde_json::Value = serde_json::from_str(&read("registry/capabilities.json")).unwrap();
|
|
for c in export["capabilities"].as_array().unwrap() {
|
|
let want = match c["capability"].as_str().unwrap() {
|
|
CAP_NEURAL_INT_SYNTH => serde_json::json!({ "set": "wai-ops/1", "profile": "acc64", "subset": "full", "lowering": "int_synth/1" }),
|
|
// DRED's feature decoder (extensions/opus-dred.md §4.8): its range decoder is
|
|
// RFC 6716's, not a stage operator, so no `stage`.
|
|
CAP_AUDIO_OPUS_DRED_INT => serde_json::json!({ "set": "wai-ops/1", "profile": "acc64", "subset": "full", "lowering": "dred-int/1" }),
|
|
// The face generator (extensions/avatars.md §7.6): its driver's steps are its
|
|
// own (§7.5), not stage operators, so no `stage`.
|
|
CAP_AVATAR_FACE => serde_json::json!({ "set": "wai-ops/1", "profile": "acc64", "subset": "full", "lowering": "face-int/1" }),
|
|
CAP_SPLAT_INT_CODEC => serde_json::json!({
|
|
"set": "wai-ops/1", "profile": "acc64", "subset": "full", "lowering": "whm1/1",
|
|
"stage": { "rans64": { "table": "t4097", "escape": "lenient", "end": "canonical" } }
|
|
}),
|
|
CAP_AUDIO_INT_CODEC => serde_json::json!({
|
|
"set": "wai-ops/1", "profile": "acc64", "subset": "full", "lowering": "wam1/1",
|
|
"stage": { "rans64": { "table": "t4097", "escape": "lenient", "end": "canonical" } }
|
|
}),
|
|
CAP_NEURAL_INT_HYPER | CAP_VIDEO_INT_HYPER => serde_json::json!({
|
|
"set": "wai-ops/1", "profile": "acc64", "subset": "full", "lowering": "whm1/1",
|
|
"stage": { "rans64": { "table": "t4097", "escape": "lenient", "end": "canonical" }, "bucket": "ceil" }
|
|
}),
|
|
c if STAGE_ONLY.contains(&c) => serde_json::json!({
|
|
"set": "wai-ops/1",
|
|
"stage": { "rans64": { "table": "t4097", "escape": "lenient", "end": "canonical" } }
|
|
}),
|
|
CAP_IMAGE_JPEGAI => serde_json::json!({
|
|
"set": "wai-ops/1", "profile": "acc64", "subset": "full", "lowering": "jpegai-int/1",
|
|
"role_profiles": { "hs_y": "acc32", "hs_uv": "acc32" }
|
|
}),
|
|
CAP_NEURAL_INT_MLICPP => serde_json::json!({
|
|
"set": "wai-ops/1", "profile": "acc64", "subset": "full", "lowering": "wmb1/1",
|
|
"stage": { "rans64": { "table": "t2", "escape": "lenient", "end": "final_only" }, "bucket": "ceil" }
|
|
}),
|
|
_ => serde_json::Value::Null,
|
|
};
|
|
assert_eq!(c["ops"], want, "{}", c["capability"]);
|
|
}
|
|
}
|
|
|
|
/// The schema's enums are the label sets the registry uses.
|
|
#[test]
|
|
fn registry_schema_enums_equal_labels() {
|
|
let schema: serde_json::Value = serde_json::from_str(&read("registry/capabilities.schema.json")).unwrap();
|
|
let props = &schema["properties"]["capabilities"]["items"]["properties"];
|
|
let enum_of = |field: &str| -> Vec<String> {
|
|
let e = props[field]["enum"].as_array().unwrap_or_else(|| panic!("{field} has no enum"));
|
|
e.iter().filter_map(|v| v.as_str().map(String::from)).collect()
|
|
};
|
|
let labels = |v: Vec<&str>| v.into_iter().map(String::from).collect::<Vec<_>>();
|
|
assert_eq!(enum_of("kind"), labels(Kind::all().iter().map(|k| k.label()).collect()));
|
|
assert_eq!(enum_of("status"), labels(RegistrationStatus::all().iter().map(|s| s.label()).collect()));
|
|
assert_eq!(enum_of("media"), labels(Media::all().iter().map(|m| m.label()).collect()));
|
|
assert_eq!(enum_of("role"), labels(ROLE_LABELS.to_vec()));
|
|
assert_eq!(enum_of("tier"), labels(FidelityTier::all().iter().map(|t| t.label()).collect()));
|
|
assert_eq!(enum_of("licence"), labels(LicenseClass::all().iter().map(|l| l.label()).collect()));
|
|
assert_eq!(enum_of("replicate"), labels(ReplicateClass::all().iter().map(|r| r.label()).collect()));
|
|
// Every value the export writes is in its enum.
|
|
let export: serde_json::Value = serde_json::from_str(&read("registry/capabilities.json")).unwrap();
|
|
for c in export["capabilities"].as_array().unwrap() {
|
|
for field in ["kind", "status", "media", "role", "tier", "licence", "replicate"] {
|
|
let v = &c[field];
|
|
let allowed = &props[field]["enum"];
|
|
assert!(allowed.as_array().unwrap().contains(v), "{}: {field} {v} not in the schema", c["capability"]);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// The backticked `wai.*` strings of `wai/SPEC.md` and the export name the same
|
|
/// set: every string SPEC uses is a registered string, an identifier, or a
|
|
/// pattern (`wai.derive.*`) that matches registered strings; and every
|
|
/// registered string appears in SPEC, literally or under a pattern SPEC states
|
|
/// as a group registration.
|
|
#[test]
|
|
fn spec_and_registry_name_the_same_strings() {
|
|
let spec = read("SPEC.md");
|
|
let mut used: Vec<String> = Vec::new();
|
|
for (i, _) in spec.match_indices("`wai.") {
|
|
let rest = &spec[i + 1..];
|
|
let end = rest.find('`').unwrap_or(0);
|
|
let s = &rest[..end];
|
|
if s.chars().all(|c| c.is_ascii_lowercase() || c.is_ascii_digit() || matches!(c, '.' | '_' | '*')) {
|
|
used.push(s.to_string());
|
|
}
|
|
}
|
|
used.sort();
|
|
used.dedup();
|
|
assert!(!used.is_empty());
|
|
let regs = registrations();
|
|
let registered: Vec<&str> = regs.iter().map(|r| r.capability).collect();
|
|
let ids: Vec<&str> = IDENTIFIERS.iter().map(|i| i.identifier).collect();
|
|
let mut problems = Vec::new();
|
|
for s in &used {
|
|
if let Some(prefix) = s.strip_suffix('*') {
|
|
if !registered.iter().chain(ids.iter()).any(|r| r.starts_with(prefix)) {
|
|
problems.push(format!("SPEC pattern `{s}` matches no registered string"));
|
|
}
|
|
} else if !registered.contains(&s.as_str()) && !ids.contains(&s.as_str()) {
|
|
problems.push(format!("SPEC names `{s}`, which the registry does not register"));
|
|
}
|
|
}
|
|
// Group registrations: SPEC registers the derivation operations as a group,
|
|
// `wai.derive.*`, with derived-tracks.md listing each.
|
|
const GROUPS: &[&str] = &["wai.derive."];
|
|
for r in ®s {
|
|
let literal = used.iter().any(|u| u == r.capability);
|
|
let grouped = GROUPS.iter().any(|g| r.capability.starts_with(g) && used.iter().any(|u| u == &format!("{g}*")));
|
|
if !literal && !grouped {
|
|
problems.push(format!("{} is registered but SPEC does not name it", r.capability));
|
|
}
|
|
}
|
|
for i in IDENTIFIERS {
|
|
if !used.iter().any(|u| u == i.identifier) {
|
|
problems.push(format!("identifier {} does not appear in SPEC", i.identifier));
|
|
}
|
|
}
|
|
// Every section a row names is a heading of SPEC §5.
|
|
for r in ®s {
|
|
let heading = r.spec_section.strip_prefix("§5 ").expect("a §5 section");
|
|
if !spec.lines().any(|l| l.starts_with("### ") && l[4..].starts_with(heading)) {
|
|
problems.push(format!("{}: SPEC has no §5 heading `{heading}`", r.capability));
|
|
}
|
|
}
|
|
assert!(problems.is_empty(), "SPEC and the registry disagree:\n{}", problems.join("\n"));
|
|
}
|
|
|
|
/// SPEC §5, *Payloads of the WAI-native integer codecs*, pins exactly the strings
|
|
/// and formats of `PINNED_INT_PAYLOADS`, and names each string's parameter-set
|
|
/// members as `int_payload` reads them; the extension defines each format in its
|
|
/// own section.
|
|
#[test]
|
|
fn spec_pins_the_integer_payloads_the_registry_lists() {
|
|
let spec = read("SPEC.md");
|
|
let at = spec.find("### Payloads of the WAI-native integer codecs").expect("the SPEC §5 subsection");
|
|
let section = &spec[at..];
|
|
let section = §ion[..section[4..].find("\n### ").map_or(section.len(), |e| e + 4)];
|
|
let mut rows: Vec<(String, String, String)> = Vec::new();
|
|
for line in section.lines().filter(|l| l.starts_with("| `wai.")) {
|
|
let cells: Vec<&str> = line.split('|').map(str::trim).collect();
|
|
let tick = |c: &str| c.split('`').nth(1).unwrap_or_default().to_string();
|
|
rows.push((tick(cells[1]), tick(cells[2]), cells[3].to_string()));
|
|
}
|
|
let mut want: Vec<(String, String)> = super::super::PINNED_INT_PAYLOADS.iter()
|
|
.map(|(c, m)| (c.to_string(), String::from_utf8_lossy(m).into_owned())).collect();
|
|
let mut got: Vec<(String, String)> = rows.iter().map(|(c, m, _)| (c.clone(), m.clone())).collect();
|
|
want.sort();
|
|
got.sort();
|
|
assert_eq!(got, want, "SPEC's table and PINNED_INT_PAYLOADS");
|
|
// Each row's set: its shape is the registry's, and its members are named.
|
|
let members: &[(&str, &[&str])] = &[
|
|
(CAP_VIDEO_INT_MOTION, &[]),
|
|
(CAP_VIDEO_INT_HYPER, &["g_s.whm", "h_s.whm", "entropy.json"]),
|
|
(CAP_NEURAL_INT_HYPER, &["g_s.whm", "h_s.whm", "entropy.json"]),
|
|
(CAP_AUDIO_INT_CODEC, &["model.wam"]),
|
|
(CAP_SPLAT_INT_CODEC, &["g_s.whm"]),
|
|
];
|
|
for (cap, _, set) in &rows {
|
|
let (_, names) = members.iter().find(|(c, _)| c == cap).expect("a pinned string");
|
|
let shape = match crate::codecs::parameter_set_shape(cap) {
|
|
None => "none",
|
|
Some(crate::codecs::ParameterSetShape::OneFile) => "one file",
|
|
Some(crate::codecs::ParameterSetShape::SeveralFiles) => "several files",
|
|
};
|
|
assert!(set.starts_with(shape), "{cap}: SPEC says `{set}`, the registry {shape}");
|
|
for n in *names {
|
|
assert!(set.contains(&format!("`{n}`")), "{cap}: SPEC names no `{n}`");
|
|
}
|
|
}
|
|
let ext = read("extensions/integer-payloads.md");
|
|
for (heading, magic) in [("## 3.", "WIV1"), ("## 4.", "WIH1"), ("## 5.", "WIA1"), ("## 6.", "WIS1")] {
|
|
assert!(ext.lines().any(|l| l.starts_with(heading) && l.contains(&format!("`{magic}`"))), "the extension's {heading} is {magic}");
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn vocab_v2_names_every_registered_string_and_no_candidate_as_emittable() {
|
|
let shapes = vocab_v2_shapes();
|
|
for r in registrations() {
|
|
let iri = format!("wai:{}\n", r.capability);
|
|
let in_shapes = shapes.contains(&format!(" {iri}"));
|
|
let emittable = matches!(r.kind, Kind::Payload | Kind::Companion | Kind::Refinement) && r.status == RegistrationStatus::Registered;
|
|
assert_eq!(in_shapes, emittable, "{}", r.capability);
|
|
assert!(vocab_v2_ttl().contains(&format!("wai:{} a wai:Capability", r.capability)), "{}", r.capability);
|
|
}
|
|
}
|
|
|
|
/// Every IRI v2.ttl defines (a line `wai:<local> a …`) is defined once: no
|
|
/// enumeration individual shares an IRI with another enumeration's, with a
|
|
/// property, or with a class. And the JSON-LD context maps a manifest's `kind`
|
|
/// and a component's `role` to terms of their own, not to the registry's.
|
|
#[test]
|
|
fn vocab_v2_defines_each_iri_once() {
|
|
let ttl = vocab_v2_ttl();
|
|
let mut defined: Vec<&str> = ttl
|
|
.lines()
|
|
.filter_map(|l| l.strip_prefix("wai:"))
|
|
.filter_map(|l| l.split_once(" a ").map(|(local, _)| local))
|
|
.collect();
|
|
let n = defined.len();
|
|
defined.sort_unstable();
|
|
defined.dedup();
|
|
assert_eq!(defined.len(), n, "an IRI of v2.ttl is defined twice");
|
|
for (_, prefix, labels) in enumerations() {
|
|
for l in labels {
|
|
assert!(defined.contains(&individual(prefix, l).as_str()), "{prefix}-{l}");
|
|
}
|
|
}
|
|
let ctx: serde_json::Value = serde_json::from_str(&vocab_v2_jsonld()).unwrap();
|
|
let ctx = &ctx["@context"];
|
|
assert_eq!(ctx["kind"]["@id"], format!("{VOCAB_V2_NS}payloadKind"));
|
|
assert_eq!(ctx["role"]["@id"], format!("{VOCAB_V2_NS}componentRole"));
|
|
assert_eq!(ctx["media"]["@context"]["@vocab"], format!("{VOCAB_V2_NS}media-"));
|
|
// Every term the context maps to the namespace names an IRI v2.ttl defines.
|
|
for (term, def) in ctx.as_object().unwrap().iter().filter(|(t, _)| !t.starts_with('@')) {
|
|
let id = def.get("@id").and_then(|v| v.as_str()).or_else(|| def.as_str()).unwrap_or("");
|
|
if let Some(local) = id.strip_prefix(VOCAB_V2_NS) {
|
|
assert!(defined.contains(&local), "context term {term} maps to wai:{local}, which v2.ttl does not define");
|
|
}
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn splice_replaces_only_the_generated_region() {
|
|
let md = format!("head\n{REGISTRY_MD_BEGIN}\nstale\n{REGISTRY_MD_END}\ntail\n");
|
|
let out = splice_registry_md(&md).unwrap();
|
|
assert!(out.starts_with(&format!("head\n{REGISTRY_MD_BEGIN}\n| string |")));
|
|
assert!(out.ends_with(&format!("{REGISTRY_MD_END}\ntail\n")));
|
|
assert!(!out.contains("stale"));
|
|
assert_eq!(splice_registry_md("no markers"), None);
|
|
}
|
|
|
|
/// The body of a numbered section (`§N`) or an appendix (`Appendix X`) of a WAI text:
|
|
/// from its heading to the next heading of its level or above, subsections included.
|
|
fn section_body<'a>(text: &'a str, section: &str) -> Option<&'a str> {
|
|
let level = |l: &str| l.bytes().take_while(|&b| b == b'#').count();
|
|
let mut starts = Vec::new();
|
|
let mut at = 0;
|
|
for l in text.split_inclusive('\n') {
|
|
starts.push((at, l));
|
|
at += l.len();
|
|
}
|
|
let is_heading = |l: &str| l.starts_with('#') && l[level(l)..].starts_with(' ');
|
|
let (k, (start, line)) = starts.iter().enumerate().find(|(_, (_, l))| {
|
|
is_heading(l) && {
|
|
let t = l[level(l) + 1..].trim_end();
|
|
match section.strip_prefix('§') {
|
|
Some(num) => t.starts_with(&format!("{num} ")) || t.starts_with(&format!("{num}. ")) || t == num,
|
|
None => t.starts_with(section),
|
|
}
|
|
}
|
|
})?;
|
|
let lv = level(line);
|
|
let end = starts[k + 1..].iter().find(|(_, l)| is_heading(l) && level(l) <= lv).map_or(text.len(), |(o, _)| *o);
|
|
Some(&text[*start..end])
|
|
}
|
|
|
|
/// Every wire identifier is written in the body of the section of the document it
|
|
/// names (not just somewhere in the document), and no name is listed twice with one
|
|
/// kind.
|
|
#[test]
|
|
fn wire_identifiers_are_in_their_documents() {
|
|
let mut seen = std::collections::BTreeSet::new();
|
|
for w in WIRE_IDENTIFIERS {
|
|
assert!(seen.insert((w.name, w.kind)), "{} ({}) is listed twice", w.name, w.kind.label());
|
|
let text = read(w.document);
|
|
let body = section_body(&text, w.section).unwrap_or_else(|| panic!("{} has no section {} for {}", w.document, w.section, w.name));
|
|
assert!(body.contains(w.name), "{} is not written in {} {}", w.name, w.document, w.section);
|
|
}
|
|
}
|
|
|
|
/// The schema's wire-identifier enums are the labels, and the export writes only
|
|
/// values in them.
|
|
#[test]
|
|
fn wire_identifier_schema_enums_equal_labels() {
|
|
let schema: serde_json::Value = serde_json::from_str(&read("registry/capabilities.schema.json")).unwrap();
|
|
let props = &schema["properties"]["wire_identifiers"]["items"]["properties"];
|
|
let enum_of = |field: &str| -> Vec<String> {
|
|
props[field]["enum"].as_array().unwrap_or_else(|| panic!("{field} has no enum"))
|
|
.iter().filter_map(|v| v.as_str().map(String::from)).collect()
|
|
};
|
|
assert_eq!(enum_of("kind"), WireKind::all().iter().map(|k| k.label().to_string()).collect::<Vec<_>>());
|
|
assert_eq!(enum_of("status"), WireStatus::all().iter().map(|s| s.label().to_string()).collect::<Vec<_>>());
|
|
let export: serde_json::Value = serde_json::from_str(&read("registry/capabilities.json")).unwrap();
|
|
let rows = export["wire_identifiers"].as_array().unwrap();
|
|
assert_eq!(rows.len(), WIRE_IDENTIFIERS.len());
|
|
for r in rows {
|
|
for field in ["kind", "status"] {
|
|
assert!(enum_of(field).iter().any(|e| r[field] == *e), "{field} {} is not in the schema", r[field]);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// The record and label strings copied from wai-quantum equal its constants.
|
|
#[cfg(feature = "quantum_ops")]
|
|
#[test]
|
|
fn quantum_strings_equal_the_wai_quantum_constants() {
|
|
use wai_quantum::quantum_ops as q;
|
|
assert_eq!(CAP_QUANTUM_CALIBRATION, q::CAP_QUANTUM_CALIBRATION);
|
|
assert_eq!(CAP_QUANTUM_JOB, q::CAP_QUANTUM_JOB);
|
|
let labels: Vec<&str> = UNREGISTERED_LABELS.iter().map(|l| l.label).collect();
|
|
assert_eq!(labels, [q::CAP_QUANTUM_MITIGATE, q::CAP_QUANTUM_DECODE, q::CAP_QUANTUM_COMPILE,
|
|
q::CAP_QUANTUM_REARRANGE, q::CAP_QUANTUM_QBOM, q::CAP_QUANTUM_FABRIC]);
|
|
}
|
|
}
|