macroonz_compiler/codec/types.rs
1//! The codec home's declarations: the kind, the shape a codec is written for, the wire vocabulary its members stand under, where the surface lands, and how a declaration of any of it refuses.
2//!
3//! Declarations only.
4//! Every road that reaches a private field lives in `type_guard.rs`, this file's own child, which is what makes this home's walls structural: a shape is seated by one road that refuses an empty roster, a doubled spelling, and a spelling the decode road has already taken, and there is no second road that seats one.
5
6use crate::bounded::{Bounded, Capped, NonEmpty};
7use crate::explanation::ASSUMPTION_LIMIT;
8use crate::identity::{OwnerFact, OwnerIdentity};
9
10#[path = "type_guard.rs"]
11mod guard;
12
13/// Members one declared shape may carry.
14///
15/// Every member is one framed run in the encode road and one bound local in the decode road, so a shape past this has stopped being one value's spelling; the repair is a nested member carrying its own codec rather than a longer roster here.
16pub const CODEC_MEMBER_LIMIT: usize = 64;
17
18/// Segments one rendered type path may carry.
19///
20/// A path reaching deeper has stopped naming an item and started describing a tree, and the repair is a re-export at the address rather than a longer spelling at this end.
21pub const CODEC_PATH_SEGMENT_LIMIT: usize = crate::token::RENDERED_PATH_SEGMENT_LIMIT;
22
23/// Issues one codec refusal carries before it begins counting the rest.
24///
25/// One per member seat, because the widest pass asks one question of every declared member and every member can answer it at once — and a caller repairing a shape one member per attempt is a caller this home failed.
26pub const CODEC_ISSUE_LIMIT: usize = 64;
27
28/// The road a rendered surface writes one value's canonical bytes by, and the road a nested member's own type is billed for.
29pub const ENCODE_ROAD: &str = "encode_canonical";
30
31/// The road a rendered surface reads those bytes back by.
32pub const DECODE_ROAD: &str = "decode_canonical";
33
34/// The roster constant a closed choice's admitted arms are walked through.
35pub const ROSTER_CONSTANT: &str = "ALL";
36
37/// The road one arm of a closed roster answers its declared position through, one byte wide because a choice is written as one byte.
38pub const SLOT_ROAD: &str = "slot";
39
40crate::roster! {
41 /// How many of one member there are.
42 ///
43 /// Three rows and no fourth: the wire roads below stand over ONE occurrence whatever supplied it, so a cardinality decides how many times a road runs and never what the road writes.
44 pub enum Cardinality {
45 /// Exactly one, written where the shape declares it.
46 Required = "required",
47 /// One or none, written behind a presence byte.
48 Optional = "optional",
49 /// As many as the value holds, written behind a framed count.
50 Repeated = "repeated",
51 }
52}
53
54crate::roster! {
55 /// The wire shape one member is written under.
56 ///
57 /// Five rows, every one a shape the rendering can write end to end: there is no opaque arm, because a member the rendering could not write would be a member whose bytes nobody could re-read.
58 pub enum CodecMemberShape {
59 /// A count, carried at the framing width and narrowed back at the member's own type on the way in.
60 Count = "count",
61 /// Variable-length bytes, written length-prefixed.
62 Bytes = "bytes",
63 /// Variable-length text, written length-prefixed as its UTF-8 bytes and read back through a check that refuses.
64 Text = "text",
65 /// One arm of a closed roster, written as that arm's own declared position and read back by walking the roster the owner declared.
66 ClosedChoice = "closed-choice",
67 /// A nested value carrying its own codec, framed at its own length so the member after it stays readable.
68 Nested = "nested",
69 }
70}
71
72crate::roster! {
73 /// Which of the two roads a request covers.
74 pub enum CodecDirection {
75 /// Typed value to canonical bytes.
76 Encode = "encode",
77 /// Canonical bytes to typed value.
78 Decode = "decode",
79 /// Both, so neither can drift from the other.
80 RoundTrip = "round-trip",
81 }
82}
83
84crate::roster! {
85 /// Where one rendered type path is rooted.
86 ///
87 /// Four rows and none is a default: where a path is rooted is a claim about whose scope resolves it, and a rendering that guessed would put the wrong one in somebody else's crate.
88 /// The qualifier is typed here rather than smuggled as a first segment, so every segment stays an item step and the keyword roster holds on all of them.
89 pub enum PathRooting {
90 /// Rooted at the caller's own crate — rendered under the language's `crate` qualifier, so the path resolves the same wherever the surface lands.
91 CrateAbsolute = "crate-absolute",
92 /// Resolved in the scope the surface lands in, exactly as the caller spelled it.
93 InScope = "in-scope",
94 /// Rooted at the module the surface lands in, under the language's `self` qualifier.
95 SelfScoped = "self-scoped",
96 /// Rooted one module above the surface, under the language's `super` qualifier; a deeper reach is a re-export at the address rather than a longer qualifier run.
97 ParentScoped = "parent-scoped",
98 }
99}
100
101crate::roster! {
102 /// One arm of the decode refusal this home renders, by the spelling it is rendered under.
103 ///
104 /// The declared name is the arm's own Rust spelling, because this roster IS the rendered type's variant list.
105 /// Which arms name the member a read was standing at is said once, at `carries_member`.
106 pub enum DecodeRefusal {
107 /// The material ended inside a member.
108 Truncated = "Truncated",
109 /// A declared length runs past the material that remains.
110 LengthPastRemaining = "LengthPastRemaining",
111 /// A declared length does not fit an addressable width.
112 LengthPastAddressableWidth = "LengthPastAddressableWidth",
113 /// A declared count does not fit the width its member is held at.
114 CountPastDeclaredWidth = "CountPastDeclaredWidth",
115 /// Framed bytes that were to be text are not UTF-8.
116 TextNotUtf8 = "TextNotUtf8",
117 /// The member's own type refused what was read for it.
118 MemberNotAdmitted = "MemberNotAdmitted",
119 /// A slot names no arm of the roster it was declared over.
120 SlotNotAdmitted = "SlotNotAdmitted",
121 /// A nested codec refused the framed material.
122 NestedMemberRefused = "NestedMemberRefused",
123 /// A presence byte is neither of the two the encode road writes.
124 PresenceNotAdmitted = "PresenceNotAdmitted",
125 /// Material remains after the last declared member.
126 TrailingBytes = "TrailingBytes",
127 /// Every member was read and the road that assembles them refused.
128 NotAssembled = "NotAssembled",
129 }
130}
131
132/// One wire shape's bill: the roads the rendered surface calls on a member's own type.
133///
134/// A road named through a trait is written qualified, with `T` standing for the member's own type; a road named on that type itself is written bare.
135///
136/// # Authority
137///
138/// **The bill is stated and never worked around.**
139/// A member the rendering could not write end to end would be a member whose bytes nobody could re-read, so the rendering does not degrade: it calls the roads named here, and where one is absent the failure lands at the caller's site as an ordinary unresolved method.
140#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
141pub struct MemberContract {
142 /// The wire shape this row is about.
143 pub shape: CodecMemberShape,
144 /// The road the encode surface calls to read the member out.
145 pub encode_road: &'static str,
146 /// The road the decode surface calls to build the member back.
147 pub decode_road: &'static str,
148}
149
150/// The generated write operation one contract row selects.
151#[derive(Clone, Copy)]
152pub(super) enum WriteRoad {
153 /// Widen one count and write its big-endian bytes.
154 Count,
155 /// Borrow bytes through the declared trait road and frame them.
156 Bytes,
157 /// Borrow text through the declared trait road and frame its UTF-8 bytes.
158 Text,
159 /// Write the declared slot of one closed-choice arm.
160 ClosedChoice,
161 /// Call and frame one nested codec.
162 Nested,
163}
164
165/// The generated read operation one contract row selects.
166#[derive(Clone, Copy)]
167pub(super) enum ReadRoad {
168 /// Read and narrow one count.
169 Count,
170 /// Read framed bytes and ask the member type to admit them.
171 Bytes,
172 /// Read framed UTF-8 text and ask the member type to admit it.
173 Text,
174 /// Elect one arm from the owner's complete roster.
175 ClosedChoice,
176 /// Ask one nested codec to read its framed material.
177 Nested,
178}
179
180/// One authoritative contract row, with its public bill and the two internal operations that consume it.
181#[derive(Clone, Copy)]
182pub(super) struct RenderingContract {
183 /// The public statement of the member roads.
184 pub(super) bill: MemberContract,
185 /// The generated write operation.
186 pub(super) write: WriteRoad,
187 /// The generated read operation.
188 pub(super) read: ReadRoad,
189}
190
191/// One type path a rendered expression names.
192///
193/// # Bounds
194///
195/// The segments are structurally non-empty: a path naming no segment names nothing, and a rendering that wrote one would emit a bare separator.
196#[derive(Debug, Clone, PartialEq, Eq, Hash)]
197pub struct CodecTypePath {
198 rooting: PathRooting,
199 segments: NonEmpty<String, CODEC_PATH_SEGMENT_LIMIT>,
200}
201
202/// One member of a declared shape: what the owner calls it, the type it is held at, how it is written, and how many of it there are.
203///
204/// # Bounds
205///
206/// The spelling is one Rust identifier by construction, because the decode road binds a local under it and the encode road reads a field under it — and a spelling that is not one renders tokens the caller's compiler reads as something else.
207#[derive(Debug, Clone, PartialEq, Eq, Hash)]
208pub struct CodecMember {
209 spelling: String,
210 held_as: CodecTypePath,
211 shape: CodecMemberShape,
212 cardinality: Cardinality,
213}
214
215/// What the decode road does with the members once it has read them all.
216///
217/// Not an option and not a default: a total constructor and a checked one are called differently, and a rendering that guessed would either drop a refusal the owner declared or write a `?` on a value that is not a `Result`.
218#[derive(Debug, Clone, PartialEq, Eq, Hash)]
219pub enum AssemblyPosture {
220 /// The road is total: every member the decode road read is an argument, and there is nothing left to refuse.
221 Total,
222 /// The road is checked, and this is the refusal it answers with.
223 Checked {
224 /// The refusal the assembly road answers with, carried into the rendered one by a conversion this home writes.
225 refusal: CodecTypePath,
226 },
227}
228
229/// The road one decoded value is assembled by, and the posture it stands under.
230///
231/// # Bounds
232///
233/// The road is an associated road on the owner's own type, so a free function is unwritable here rather than refused: that is the shape a decode road can call without learning where the owner's module sits.
234#[derive(Debug, Clone, PartialEq, Eq, Hash)]
235pub struct CodecAssembly {
236 road: String,
237 posture: AssemblyPosture,
238}
239
240/// The complete declared shape one codec is rendered for.
241///
242/// # Bounds
243///
244/// The member set is structurally non-empty: a codec over no member writes no byte and reads none, so it could refuse for one reason and would admit every other input — and a codec that cannot refuse is not the validator this home says a codec is.
245///
246/// The rendered refusal's spelling is carried rather than derived, because it is a type declared in the caller's own scope and this home may not choose a name there.
247#[derive(Debug, Clone, PartialEq, Eq, Hash)]
248pub struct CodecShape {
249 owner: CodecTypePath,
250 refusal: String,
251 assembly: CodecAssembly,
252 members: NonEmpty<CodecMember, CODEC_MEMBER_LIMIT>,
253}
254
255/// The spelling one visibly published module is declared under.
256///
257/// # Bounds
258///
259/// One Rust identifier by construction: the module lands in the caller's own scope and shares a namespace with every other item there.
260#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
261pub struct ModuleSpelling {
262 spelling: String,
263}
264
265/// What shape the rendered surface lands in.
266///
267/// # Bounds
268///
269/// Both rows are declaration-site deliveries, so the delivery is the seat's constant answer under either and what this decides is the surface's shape alone.
270#[derive(Debug, Clone, PartialEq, Eq, Hash)]
271pub enum CodecPlacement {
272 /// Spliced beside the owner's own item, in the scope the declaration sits in.
273 AtDeclarationSite,
274 /// Wrapped in a visibly published module, whose head imports the scope the module sits in.
275 PublishedModule {
276 /// The module's declared spelling.
277 spelling: ModuleSpelling,
278 },
279}
280
281/// What one codec request carries beyond its captured tokens.
282///
283/// # Nonclaims
284///
285/// The schema and the byte role reach no token of the rendered surface: the schema is what the codec is projected FROM and the shape is what it is written FOR, and the framing is this home's whatever the bytes are called.
286/// They travel so an explanation can name them and a caller can join the surface back to the declaration it answers to.
287#[derive(Debug, Clone, PartialEq, Eq, Hash)]
288pub struct CodecContent {
289 /// The declared shape the two roads are written over.
290 pub shape: CodecShape,
291 /// Which of the two roads the surface carries.
292 pub direction: CodecDirection,
293 /// The shape the rendered surface lands in.
294 pub placement: CodecPlacement,
295 /// The schema the codec is projected from, where the caller minted one.
296 pub schema: Option<OwnerIdentity>,
297 /// The byte role naming which bytes these are, where the caller minted one.
298 pub byte_role: Option<OwnerIdentity>,
299 /// The owner facts this projection assumes.
300 pub assumptions: Bounded<OwnerFact, ASSUMPTION_LIMIT>,
301}
302
303/// Projects a declared shape into the codec that reads and writes its canonical bytes.
304///
305/// One rendered unit, at the declaration site: the surface is Rust the caller's normal build compiles, whether it is spliced beside the owner's item or wrapped in a published module.
306#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
307pub struct CodecProjection;
308
309/// How one declaration of this home's vocabulary refuses.
310///
311/// No row is payload-free where a payload would tell a caller what to repair: a row names the spelling it refused at, or the two counts a magnitude was passed by.
312#[derive(Debug, Clone, PartialEq, Eq, Hash)]
313pub enum CodecIssue {
314 /// A rendered type path names no segment, so it names nothing.
315 PathSegmentsAbsent,
316 /// A path segment cannot name a rendered item — not one Rust identifier, or a keyword the language already took — so the rendering would write tokens the caller's compiler reads as something else.
317 SegmentNotAnIdentifier {
318 /// The segment as it was spelled.
319 segment: String,
320 },
321 /// A path carries more segments than the declared magnitude.
322 PathSegmentsUnbounded {
323 /// The declared bound.
324 bound: u64,
325 /// The observed count.
326 observed: u64,
327 },
328 /// A member states no spelling, so nothing names it in either road.
329 MemberSpellingAbsent,
330 /// A member's spelling cannot name a rendered item: not one Rust identifier, or a keyword the language already took.
331 MemberSpellingNotAnIdentifier {
332 /// The spelling as it was stated.
333 spelling: String,
334 },
335 /// Two members of one shape carry one spelling, so the decode road would bind one local twice and the assembly would be handed the second.
336 MemberSpellingDoubled {
337 /// The spelling two members share.
338 spelling: String,
339 },
340 /// A member's spelling is one of the locals the decode road declares for itself, so the member's binding would shadow the rendering's and the road would go on reading a value nobody meant.
341 MemberShadowsBinding {
342 /// The member that collided.
343 spelling: String,
344 /// The binding it collided with.
345 binding: &'static str,
346 },
347 /// An assembly road states no spelling.
348 AssemblyRoadAbsent,
349 /// An assembly road's spelling cannot name a rendered item: not one Rust identifier, or a keyword the language already took.
350 AssemblyRoadNotAnIdentifier {
351 /// The spelling as it was stated.
352 spelling: String,
353 },
354 /// A rendered decode refusal's spelling cannot name a rendered item: not one Rust identifier, or a keyword the language already took.
355 RefusalSpellingNotAnIdentifier {
356 /// The spelling as it was stated.
357 spelling: String,
358 },
359 /// A published module's spelling cannot name a rendered item: not one Rust identifier, or a keyword the language already took.
360 ModuleSpellingNotAnIdentifier {
361 /// The spelling as it was stated.
362 spelling: String,
363 },
364 /// A shape declares no member at all.
365 MembersAbsent,
366 /// A shape declares more members than the declared magnitude.
367 MembersUnbounded {
368 /// The declared bound.
369 bound: u64,
370 /// The observed count.
371 observed: u64,
372 },
373}
374
375/// How declaring a codec says no.
376///
377/// The passes that reach it are dependent in a stated order, so exactly one cause is true of a refused path, spelling, or road — while the pass over a shape's members co-establishes freely, because a caller told about one colliding member and not the next is a caller who repairs a shape one attempt at a time.
378#[must_use = "a codec refusal names the exact seat the declaration did not fill"]
379#[derive(Debug, Clone, PartialEq, Eq, Hash)]
380pub struct CodecError {
381 body: Capped<CodecIssue, CODEC_ISSUE_LIMIT>,
382}
383
384/// The one alphabet every spelling this home renders as a Rust identifier is admitted by, published from the nucleus every road here already reads it through.
385pub use guard::{rendered_identifier, rendered_name};