Skip to main content

type_bridge_contract/
limits.rs

1//! Canonical implementation-independent codec ceilings.
2
3/// Maximum canonical artifact size: 16 MiB.
4pub const MAX_CANONICAL_BYTES: usize = 16 * 1024 * 1024;
5/// Maximum remote request/response envelope size: 32 MiB.
6///
7/// Remote envelopes embed a canonical plan plus invocation rows and framing,
8/// so their owning-format budget is deliberately larger than the plan codec's
9/// 16 MiB ceiling while remaining independently bounded.
10pub const MAX_REMOTE_ENVELOPE_BYTES: usize = 32 * 1024 * 1024;
11/// Maximum JSON nesting depth, counting the root as one.
12pub const MAX_CANONICAL_DEPTH: usize = 64;
13/// Maximum direct members in one array or object.
14pub const MAX_CANONICAL_COLLECTION_LEN: usize = 65_536;
15/// Maximum UTF-8 byte length of one string or object key: 1 MiB.
16pub const MAX_CANONICAL_STRING_BYTES: usize = 1024 * 1024;
17
18/// The complete canonical JSON structural limit set.
19#[derive(Debug, Clone, Copy, PartialEq, Eq)]
20pub struct CodecLimits {
21    /// Maximum encoded or decoded bytes.
22    pub max_bytes: usize,
23    /// Maximum nested value depth.
24    pub max_depth: usize,
25    /// Maximum direct collection members.
26    pub max_collection_len: usize,
27    /// Maximum bytes in one string or key.
28    pub max_string_bytes: usize,
29}
30
31impl CodecLimits {
32    /// Canonical Phase 1 codec limits.
33    pub const CANONICAL: Self = Self {
34        max_bytes: MAX_CANONICAL_BYTES,
35        max_depth: MAX_CANONICAL_DEPTH,
36        max_collection_len: MAX_CANONICAL_COLLECTION_LEN,
37        max_string_bytes: MAX_CANONICAL_STRING_BYTES,
38    };
39}
40
41impl Default for CodecLimits {
42    fn default() -> Self {
43        Self::CANONICAL
44    }
45}
46
47/// Canonical limits used by every contract codec consumer.
48pub const CANONICAL_CODEC_LIMITS: CodecLimits = CodecLimits::CANONICAL;
49
50/// Owning-format limits for V1 remote replies and capability advertisements.
51pub const REMOTE_ENVELOPE_CODEC_LIMITS: CodecLimits = CodecLimits {
52    max_bytes: MAX_REMOTE_ENVELOPE_BYTES,
53    max_depth: MAX_CANONICAL_DEPTH,
54    max_collection_len: MAX_CANONICAL_COLLECTION_LEN,
55    max_string_bytes: MAX_CANONICAL_STRING_BYTES,
56};
57
58/// Owning-format limits for V1 remote query request envelopes.
59///
60/// A request embeds an independently canonical plan beneath exactly one
61/// framing object. The extra level admits a standalone plan at the canonical
62/// depth boundary without relaxing that plan's own revalidation or the limits
63/// for replies and capability advertisements.
64pub const REMOTE_REQUEST_CODEC_LIMITS: CodecLimits = CodecLimits {
65    max_bytes: MAX_REMOTE_ENVELOPE_BYTES,
66    max_depth: MAX_CANONICAL_DEPTH + 1,
67    max_collection_len: MAX_CANONICAL_COLLECTION_LEN,
68    max_string_bytes: MAX_CANONICAL_STRING_BYTES,
69};
70
71/// Maximum number of selected output slots in one typed plan.
72pub const MAX_SELECTED_SLOTS: usize = 16;
73/// Maximum number of bindings in one typed plan.
74pub const MAX_BINDINGS: usize = 256;
75/// Maximum number of nodes in one predicate tree.
76pub const MAX_PREDICATE_NODES: usize = 4_096;
77/// Maximum predicate nesting depth, counting a root as depth one.
78pub const MAX_PREDICATE_DEPTH: usize = 64;
79/// Maximum number of children in one boolean expression.
80pub const MAX_BOOLEAN_TERMS: usize = 256;
81/// Maximum number of explicitly allowed cross-join binding pairs.
82pub const MAX_ALLOWED_CROSS_JOINS: usize = 1_024;
83/// Maximum number of public row/root ordering terms.
84pub const MAX_ORDER_TERMS: usize = 64;
85/// Maximum number of ordering terms for one collected output slot.
86pub const MAX_COLLECTION_ORDER_TERMS: usize = 64;
87/// Maximum number of input rows in one typed invocation.
88pub const MAX_INPUT_ROWS: usize = 4_096;
89/// Maximum encoded bytes across one invocation's input-row batch: 4 MiB.
90pub const MAX_INPUT_BYTES: usize = 4 * 1024 * 1024;
91/// Maximum canonical bytes in one complete plan-bound query invocation.
92///
93/// The owning wire object adds 234 fixed bytes around the independently
94/// bounded input-row batch: the `inputs` key, the longest operation spelling
95/// (`exists`), and the fixed-domain query-plan fingerprint. Contract tests
96/// construct an invocation whose input batch is exactly [`MAX_INPUT_BYTES`]
97/// and prove that this ceiling is both attainable and one-byte tight.
98pub const MAX_QUERY_INVOCATION_BYTES: usize = MAX_INPUT_BYTES + 234;
99/// Maximum UTF-8 bytes in one output or query-variable name.
100pub const MAX_OUTPUT_NAME_BYTES: usize = 128;
101/// Maximum UTF-8 bytes in one serialized semantic identity.
102pub const MAX_SEMANTIC_ID_BYTES: usize = 512;
103/// Maximum bytes in one canonical serialized diagnostic.
104pub const MAX_DIAGNOSTIC_BYTES: usize = 65_536;
105
106/// Shared implementation-independent typed-plan structural ceilings.
107#[derive(Debug, Clone, Copy, PartialEq, Eq)]
108pub struct StructuralLimits {
109    /// Selected output slots.
110    pub selected_slots: usize,
111    /// Plan bindings.
112    pub bindings: usize,
113    /// Total predicate nodes.
114    pub predicate_nodes: usize,
115    /// Predicate-tree depth.
116    pub predicate_depth: usize,
117    /// Children in one boolean expression.
118    pub boolean_terms: usize,
119    /// Explicitly allowed cross joins.
120    pub allowed_cross_joins: usize,
121    /// Public row/root ordering terms.
122    pub order_terms: usize,
123    /// Per-collection ordering terms.
124    pub collection_order_terms: usize,
125    /// Input rows in one invocation.
126    pub input_rows: usize,
127    /// Encoded bytes across one invocation's input rows.
128    pub input_bytes: usize,
129    /// Named output-slot UTF-8 bytes.
130    pub output_name_bytes: usize,
131    /// Semantic identity UTF-8 bytes.
132    pub semantic_id_bytes: usize,
133    /// Canonical diagnostic bytes.
134    pub diagnostic_bytes: usize,
135}
136
137impl StructuralLimits {
138    /// Canonical cross-language protocol limits.
139    pub const CANONICAL: Self = Self {
140        selected_slots: MAX_SELECTED_SLOTS,
141        bindings: MAX_BINDINGS,
142        predicate_nodes: MAX_PREDICATE_NODES,
143        predicate_depth: MAX_PREDICATE_DEPTH,
144        boolean_terms: MAX_BOOLEAN_TERMS,
145        allowed_cross_joins: MAX_ALLOWED_CROSS_JOINS,
146        order_terms: MAX_ORDER_TERMS,
147        collection_order_terms: MAX_COLLECTION_ORDER_TERMS,
148        input_rows: MAX_INPUT_ROWS,
149        input_bytes: MAX_INPUT_BYTES,
150        output_name_bytes: MAX_OUTPUT_NAME_BYTES,
151        semantic_id_bytes: MAX_SEMANTIC_ID_BYTES,
152        diagnostic_bytes: MAX_DIAGNOSTIC_BYTES,
153    };
154
155    /// Return whether `actual` fits the selected-slot ceiling.
156    pub const fn allows_selected_slots(self, actual: usize) -> bool {
157        actual <= self.selected_slots
158    }
159
160    /// Return whether `actual` fits the binding ceiling.
161    pub const fn allows_bindings(self, actual: usize) -> bool {
162        actual <= self.bindings
163    }
164
165    /// Return whether `actual` fits the invocation input-row ceiling.
166    pub const fn allows_input_rows(self, actual: usize) -> bool {
167        actual <= self.input_rows
168    }
169
170    /// Return whether `actual` fits the invocation input-byte ceiling.
171    pub const fn allows_input_bytes(self, actual: usize) -> bool {
172        actual <= self.input_bytes
173    }
174
175    /// Return whether `actual` fits the public ordering-term ceiling.
176    pub const fn allows_order_terms(self, actual: usize) -> bool {
177        actual <= self.order_terms
178    }
179
180    /// Return whether `actual` fits the predicate-node ceiling.
181    pub const fn allows_predicate_nodes(self, actual: usize) -> bool {
182        actual <= self.predicate_nodes
183    }
184
185    /// Return whether `actual` fits the predicate-depth ceiling.
186    pub const fn allows_predicate_depth(self, actual: usize) -> bool {
187        actual <= self.predicate_depth
188    }
189
190    /// Return whether `actual` fits the diagnostic-byte ceiling.
191    pub const fn allows_diagnostic_bytes(self, actual: usize) -> bool {
192        actual <= self.diagnostic_bytes
193    }
194}
195
196impl Default for StructuralLimits {
197    fn default() -> Self {
198        Self::CANONICAL
199    }
200}
201
202/// Canonical structural limits shared by V1 and V2 typed plans.
203pub const CANONICAL_STRUCTURAL_LIMITS: StructuralLimits = StructuralLimits::CANONICAL;