Skip to main content

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}