macroonz_compiler/render/types.rs
1//! The render home's declarations: the ceiling one rendered unit's bytes stand under, one materialized unit, the whole rendering, the sink a renderer writes into, and how rendering says no.
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 the digest structural: it is taken there over the tree's own canonical bytes, and no caller supplies one.
5
6use crate::bounded::NonEmpty;
7use crate::identity::{self, Identity, OwnerIdentity, Profile};
8use crate::kind::{Kind, Role};
9use crate::origin::OriginTrail;
10use crate::plan::{MEMBERSHIP_LIMIT, Plan};
11use crate::token::GeneratedTree;
12
13#[path = "type_guard.rs"]
14mod guard;
15
16/// Bytes one rendered unit may carry.
17///
18/// A renderer that would emit past this refuses rather than materializing part of a unit.
19pub const RENDERED_BYTE_LIMIT: usize = 65_536;
20
21/// One unit a renderer actually materialized.
22///
23/// Its seat and every fact that seat's planned member states are carried, so a proof can rebuild a membership out of a rendering and compare it against the declared one; the tree, the identity, and the digest are the rendering's own.
24///
25/// # Nonclaims
26///
27/// The Rust source text is not a member of the unit.
28/// It is [`GeneratedTree::inspected`](crate::token::GeneratedTree::inspected) — a projection of the tree, for a person.
29#[derive(Debug, Clone, PartialEq, Eq)]
30pub struct RenderedUnit<R: Role> {
31 role: R,
32 identity: Identity<identity::RenderedUnit>,
33 semantic_key: Identity<identity::GeneratedUnit>,
34 profile: Profile,
35 origin: OriginTrail,
36 address: Option<OwnerIdentity>,
37 tree: GeneratedTree,
38 digest: Identity<identity::OutputBytes>,
39}
40
41/// Everything one renderer produced for one plan.
42///
43/// Structurally non-empty: a rendering that materialized nothing is not a rendering, and no plan can ever close over one.
44/// Bounded by the magnitude a plan declares its membership inside, because a rendering wider than any plan could declare has no plan to close over.
45#[derive(Debug, Clone, PartialEq, Eq)]
46pub struct RenderedProjection<R: Role> {
47 units: NonEmpty<RenderedUnit<R>, MEMBERSHIP_LIMIT>,
48}
49
50/// The value a renderer writes its units into.
51///
52/// It holds the plan, so a renderer names a seat and hands over tokens: everything else one unit carries is that seat's planned member, read here.
53/// It holds no proof and makes none — a seat left unfilled and a seat filled twice are written into it as freely as an honest rendering, because those are disagreements between a rendering and a plan and the proof that compares the two is what settles them.
54pub struct Output<'plan, K: Kind> {
55 plan: &'plan Plan<K>,
56 units: Vec<RenderedUnit<K::Role>>,
57}
58
59/// How rendering says no.
60///
61/// One refusal, at the first thing that goes wrong: a unit that cannot be materialized is not a unit, and the units after it were never written.
62/// Three rows name a declared magnitude and the two counts that passed it; the other two say a rendering and a plan's seats do not line up at all.
63#[must_use = "a rendering refusal names the seat or the magnitude the renderer would have passed"]
64#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
65pub enum RenderError {
66 /// The renderer wrote no unit at all.
67 NothingRendered,
68 /// A unit was written under a seat this plan declares no member for.
69 ///
70 /// Refused where it is written rather than where a proof would notice it, because a unit answers to its member's semantic key and a seat with no member offers none.
71 SeatUnplanned {
72 /// The seat's declared name.
73 role: &'static str,
74 },
75 /// One unit's canonical bytes pass the declared magnitude.
76 BytesUnbounded {
77 /// The seat the unit was written under, by its declared name.
78 role: &'static str,
79 /// The declared bound.
80 bound: usize,
81 /// The observed count.
82 observed: usize,
83 },
84 /// The rendering carries more units than the declared magnitude admits.
85 UnitsUnbounded {
86 /// The declared bound.
87 bound: usize,
88 /// The observed count.
89 observed: usize,
90 },
91 /// A generated tree passed the declared per-level magnitude while a unit was being composed.
92 ///
93 /// The one overflow a renderer meets: the composition helpers and the tree assembler are what it builds with, and they are the only roads it takes that bound anything.
94 TokensUnbounded {
95 /// The declared bound.
96 bound: usize,
97 /// The observed count.
98 observed: usize,
99 },
100}