Skip to main content

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::{
12    CAPTURED_TOKEN_LIMIT, GeneratedTree, TEXT_SOURCE_BYTE_LIMIT, TOKEN_PATH_DEPTH_LIMIT,
13};
14
15#[path = "type_guard.rs"]
16mod guard;
17
18const CAPTURED_TOKENS_PER_PATH_LEVEL: usize = CAPTURED_TOKEN_LIMIT
19    .checked_div(TOKEN_PATH_DEPTH_LIMIT)
20    .expect("the nonzero token-path depth divides the captured-token magnitude");
21
22/// Bytes one rendered unit may carry.
23///
24/// Derived from the complete callable source magnitude and per-level token magnitude, amortized across the declared nesting depth.
25/// The limit applies to canonical output bytes independently of which capture road supplied the declaration.
26///
27/// A renderer that would emit past this refuses rather than materializing part of a unit.
28pub const RENDERED_BYTE_LIMIT: usize = TEXT_SOURCE_BYTE_LIMIT * CAPTURED_TOKENS_PER_PATH_LEVEL;
29
30/// One unit a renderer actually materialized.
31///
32/// 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.
33///
34/// # Nonclaims
35///
36/// The Rust source text is not a member of the unit.
37/// It is [`GeneratedTree::inspected`](crate::token::GeneratedTree::inspected) — a projection of the tree, for a person.
38#[derive(Debug, Clone, PartialEq, Eq)]
39pub struct RenderedUnit<R: Role> {
40    role: R,
41    identity: Identity<identity::RenderedUnit>,
42    semantic_key: Identity<identity::GeneratedUnit>,
43    profile: Profile,
44    origin: OriginTrail,
45    address: Option<OwnerIdentity>,
46    tree: GeneratedTree,
47    digest: Identity<identity::OutputBytes>,
48}
49
50/// Everything one renderer produced for one plan.
51///
52/// Structurally non-empty: a rendering that materialized nothing is not a rendering, and no plan can ever close over one.
53/// 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.
54#[derive(Debug, Clone, PartialEq, Eq)]
55pub struct RenderedProjection<R: Role> {
56    units: NonEmpty<RenderedUnit<R>, MEMBERSHIP_LIMIT>,
57}
58
59/// The value a renderer writes its units into.
60///
61/// 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.
62/// 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.
63pub struct Output<'plan, K: Kind> {
64    plan: &'plan Plan<K>,
65    units: Vec<RenderedUnit<K::Role>>,
66}
67
68/// How rendering says no.
69///
70/// 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.
71/// 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.
72#[must_use = "a rendering refusal names the seat or the magnitude the renderer would have passed"]
73#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
74pub enum RenderError {
75    /// The renderer wrote no unit at all.
76    NothingRendered,
77    /// A unit was written under a seat this plan declares no member for.
78    ///
79    /// 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.
80    SeatUnplanned {
81        /// The seat's declared name.
82        role: &'static str,
83    },
84    /// One unit's canonical bytes pass the declared magnitude.
85    BytesUnbounded {
86        /// The seat the unit was written under, by its declared name.
87        role: &'static str,
88        /// The declared bound.
89        bound: usize,
90        /// The observed count.
91        observed: usize,
92    },
93    /// The rendering carries more units than the declared magnitude admits.
94    UnitsUnbounded {
95        /// The declared bound.
96        bound: usize,
97        /// The observed count.
98        observed: usize,
99    },
100    /// A generated tree passed the declared per-level magnitude while a unit was being composed.
101    ///
102    /// 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.
103    TokensUnbounded {
104        /// The declared bound.
105        bound: usize,
106        /// The observed count.
107        observed: usize,
108    },
109}