alux_shape/algebra.rs
1//! The sorts of a data shape, and the primitives over them.
2
3/// A name: the words it is made of, in order.
4///
5/// Spelling is not part of a name. An interpretation joins these words however it spells names, so
6/// the same term reads `displayName` in one and `display_name` in another without either
7/// re-segmenting anything — which is what makes the spelling exact rather than a conversion's guess.
8pub type Words<'a> = &'a [&'a str];
9
10/// The sorts of a data shape.
11///
12/// A pure carrier trait, shared by the classes below so the sorts stay linked with no equality
13/// bounds and no per-class re-declaration.
14pub trait Sorts {
15 /// A shape.
16 type Ty;
17 /// One member of a product.
18 type Field;
19}
20
21/// The shape sort: what data is, and how it is written.
22pub trait ShapeAlg: Sorts {
23 /// A boolean.
24 fn truth(&self) -> Self::Ty;
25
26 /// The empty value: `null`, or an absent member.
27 fn unit(&self) -> Self::Ty;
28
29 /// Text.
30 fn text(&self) -> Self::Ty;
31
32 /// One fixed piece of text, as a value: content that happens to be constant.
33 fn literal(&self, text: &str) -> Self::Ty;
34
35 /// A value whose content is a name, spelled however the interpretation spells names.
36 ///
37 /// What a discriminant carries, and what a choice between names alone is made of. Distinct from
38 /// [`ShapeAlg::literal`] because a name is words and a literal is already text.
39 fn name_word(&self, words: Words<'_>) -> Self::Ty;
40
41 /// An integer of a stated width and signedness.
42 fn int(&self, signed: bool, bits: u16) -> Self::Ty;
43
44 /// A floating-point number of a stated width.
45 fn float(&self, bits: u16) -> Self::Ty;
46
47 /// Opaque bytes, of a stated length when fixed.
48 fn bytes(&self, len: Option<usize>) -> Self::Ty;
49
50 /// Written as `0x`-prefixed hexadecimal, rather than however the item would appear alone.
51 fn hex(&self, item: Self::Ty) -> Self::Ty;
52
53 /// Written as decimal digits in text, which is what a width beyond a JSON number requires.
54 fn decimal(&self, item: Self::Ty) -> Self::Ty;
55
56 /// Written as base64 text.
57 fn base64(&self, item: Self::Ty) -> Self::Ty;
58
59 /// A value that may be absent.
60 fn opt(&self, item: Self::Ty) -> Self::Ty;
61
62 /// An ordered sequence of one shape.
63 fn seq(&self, item: Self::Ty) -> Self::Ty;
64
65 /// An association from one shape to another.
66 fn map(&self, key: Self::Ty, value: Self::Ty) -> Self::Ty;
67
68 /// A product of members.
69 fn product(&self, fields: Vec<Self::Field>) -> Self::Ty;
70
71 /// A choice between alternatives, carrying no discriminant of its own.
72 ///
73 /// Every encoding that does write one is derived from this — see the extension in `derived`.
74 fn choice(&self, alternatives: Vec<Self::Ty>) -> Self::Ty;
75
76 /// Introduces a name for a shape, so an interpretation can state it once.
77 ///
78 /// A name is an identity, not an instruction: an interpretation that declares types emits one
79 /// and refers to it, and one that types structurally may spell the shape at each use.
80 fn named(&self, words: Words<'_>, body: Self::Ty) -> Self::Ty;
81
82 /// Uses a name introduced elsewhere, which is what makes recursion expressible.
83 fn reference(&self, words: Words<'_>) -> Self::Ty;
84}
85
86/// The member sort: the ways one member of a product arises.
87pub trait FieldAlg: Sorts {
88 /// A member under the name it is written with.
89 fn field(&self, words: Words<'_>, shape: Self::Ty) -> Self::Field;
90
91 /// Another product's members, observed as this product's own.
92 ///
93 /// Not a member, but two products seen as one. Taking a shape and answering with a member is
94 /// what makes merging a non-product inexpressible.
95 fn merge(&self, shape: Self::Ty) -> Self::Field;
96}