pub enum Ty {
Text,
Number,
Bool,
Bytes,
Image,
Document,
Json,
List(Box<Ty>),
Record(BTreeMap<String, Ty>),
}Expand description
The shape of a value flowing through a pipeline.
Deliberately small. This exists to catch the mistake that actually happens
when blocks are composed — one block emitting a summary string into another
expecting a list of chunks — not to be a general-purpose type system. A
richer one would need inference, and inference over a language with no
expressions is machinery without a use.
Written and read as a compact string — text, [text], {path: text} —
rather than as a nested tagged object.
Two reasons, and the second is the one that forced it. It reads well in an
error message and in a spec, so one syntax serves the wire, the diagnostics,
and the DSL. And a recursive enum serialized structurally makes serde’s
generic serializer recurse deeply enough to blow rustc’s recursion limit in
the guest crate — which would have meant every block author adding
#![recursion_limit] to work around a detail of this type.
Variants§
Text
A UTF-8 string.
Number
A JSON number, integral or fractional.
One variant rather than an int/float pair: JSON itself does not
distinguish them, so a block returning 3 where 3.0 was meant would
fail a check that exists only in the type system and nowhere in the
data. Where the distinction matters downstream — a Parquet column type,
say — it is decided by looking at the values, which is the only place
the information actually exists.
Bool
A JSON boolean.
Bytes
Opaque bytes, base64-encoded on the wire.
Image
A handle naming an image the host holds.
Document
A handle naming a paged document.
Json
Any JSON value. The top type: everything is assignable to it.
An escape hatch, and one worth using sparingly — a pipeline of Json
seams typechecks unconditionally, which is the same as not checking.
List(Box<Ty>)
An ordered sequence.
Record(BTreeMap<String, Ty>)
A fixed set of named fields.
A BTreeMap so that two records written in different field orders are
the same type, and so error messages list fields the same way twice.
Implementations§
Source§impl Ty
impl Ty
Sourcepub fn assignable_to(&self, expected: &Ty) -> bool
pub fn assignable_to(&self, expected: &Ty) -> bool
Whether a value of this type can be fed where expected is required.
Not equality: Ty::Json accepts anything, and a record with extra
fields satisfies one that needs fewer. Both directions of that matter —
a block that adds a field should not break its consumer, and a block
that requires a field its producer never emits should fail loudly.
Sourcepub fn matches_value(&self, value: &Value) -> bool
pub fn matches_value(&self, value: &Value) -> bool
Whether a live JSON value could plausibly be an instance of this
type — a runtime counterpart to Self::assignable_to, which only
ever compares two declared Tys against each other. Nothing in the
host checked a block’s actual output against what it declared
until this existed: a block could claim {summary: text} and return
{text: "..."} and nothing downstream would notice until whatever
consumed summary got null.
Deliberately permissive, not a full validator: Ty::Bytes,
Ty::Image, and Ty::Document have no fixed JSON shape defined
anywhere in this protocol (unlike Ty::Text/Ty::List/
Ty::Record, which map onto JSON strings/arrays/objects
unambiguously) — inventing a shape for them here risks rejecting
legitimate values a real block already produces. Those three, like
Ty::Json, accept anything.