vyre_runtime/megakernel/
protocol_api.rs1mod publish;
4pub use publish::RingSlotTransition;
5
6use crate::PipelineError;
7
8use super::protocol::{self, DebugRecord};
9use super::Megakernel;
10
11impl Megakernel {
12 #[must_use]
14 pub fn control_byte_len(observable_slots: u32) -> Option<usize> {
15 protocol::control_byte_len(observable_slots)
16 }
17
18 #[must_use]
20 pub fn ring_byte_len(slot_count: u32) -> Option<usize> {
21 protocol::ring_byte_len(slot_count)
22 }
23
24 #[must_use]
26 pub fn debug_log_byte_len(record_capacity: u32) -> Option<usize> {
27 protocol::debug_log_byte_len(record_capacity)
28 }
29
30 #[must_use]
32 pub fn debug_record_capacity() -> u32 {
33 protocol::debug::RECORD_CAPACITY
34 }
35
36 pub fn encode_control(
43 shutdown: bool,
44 tenant_count: u32,
45 observable_slots: u32,
46 ) -> Result<Vec<u8>, PipelineError> {
47 protocol::encode_control(shutdown, tenant_count, observable_slots).map_err(protocol_error)
48 }
49
50 pub fn try_encode_control(
57 shutdown: bool,
58 tenant_count: u32,
59 observable_slots: u32,
60 ) -> Result<Vec<u8>, PipelineError> {
61 Self::encode_control(shutdown, tenant_count, observable_slots)
62 }
63
64 pub fn try_encode_control_into(
71 shutdown: bool,
72 tenant_count: u32,
73 observable_slots: u32,
74 dst: &mut Vec<u8>,
75 ) -> Result<(), PipelineError> {
76 protocol::try_encode_control_into(shutdown, tenant_count, observable_slots, dst)
77 .map_err(protocol_error)
78 }
79
80 pub fn encode_empty_ring(slot_count: u32) -> Result<Vec<u8>, PipelineError> {
87 protocol::encode_empty_ring(slot_count).map_err(protocol_error)
88 }
89
90 pub fn try_encode_empty_ring(slot_count: u32) -> Result<Vec<u8>, PipelineError> {
97 Self::encode_empty_ring(slot_count)
98 }
99
100 pub fn try_encode_empty_ring_into(
107 slot_count: u32,
108 dst: &mut Vec<u8>,
109 ) -> Result<(), PipelineError> {
110 protocol::try_encode_empty_ring_into(slot_count, dst).map_err(protocol_error)
111 }
112
113 pub fn encode_empty_debug_log(record_capacity: u32) -> Result<Vec<u8>, PipelineError> {
119 protocol::encode_empty_debug_log(record_capacity).map_err(protocol_error)
120 }
121
122 pub fn try_encode_empty_debug_log(record_capacity: u32) -> Result<Vec<u8>, PipelineError> {
128 Self::encode_empty_debug_log(record_capacity)
129 }
130
131 pub fn try_encode_empty_debug_log_into(
137 record_capacity: u32,
138 dst: &mut Vec<u8>,
139 ) -> Result<(), PipelineError> {
140 protocol::try_encode_empty_debug_log_into(record_capacity, dst).map_err(protocol_error)
141 }
142
143 #[must_use]
145 pub fn read_done_count(control_bytes: &[u8]) -> u32 {
146 protocol::read_done_count(control_bytes)
147 }
148
149 pub fn try_read_done_count(control_bytes: &[u8]) -> Result<u32, PipelineError> {
156 protocol::try_read_done_count(control_bytes).map_err(protocol_error)
157 }
158
159 pub fn try_count_done_ring_slots(
166 ring_bytes: &[u8],
167 item_count: usize,
168 ) -> Result<u64, PipelineError> {
169 protocol::try_count_done_ring_slots(ring_bytes, item_count).map_err(protocol_error)
170 }
171
172 #[must_use]
174 pub fn read_debug_log(debug_bytes: &[u8]) -> Vec<DebugRecord> {
175 protocol::read_debug_log(debug_bytes)
176 }
177
178 pub fn read_debug_log_into(debug_bytes: &[u8], out: &mut Vec<DebugRecord>) {
180 protocol::read_debug_log_into(debug_bytes, out);
181 }
182
183 pub fn try_read_debug_log(debug_bytes: &[u8]) -> Result<Vec<DebugRecord>, PipelineError> {
190 protocol::try_read_debug_log(debug_bytes).map_err(protocol_error)
191 }
192
193 pub fn try_read_debug_log_into(
200 debug_bytes: &[u8],
201 out: &mut Vec<DebugRecord>,
202 ) -> Result<(), PipelineError> {
203 protocol::try_read_debug_log_into(debug_bytes, out).map_err(protocol_error)
204 }
205
206 #[must_use]
210 pub fn read_epoch(control_bytes: &[u8]) -> u32 {
211 protocol::read_epoch(control_bytes)
212 }
213
214 pub fn try_read_epoch(control_bytes: &[u8]) -> Result<u32, PipelineError> {
221 protocol::try_read_epoch(control_bytes).map_err(protocol_error)
222 }
223
224 #[must_use]
228 pub fn read_observable(control_bytes: &[u8], index: u32) -> u32 {
229 protocol::read_observable(control_bytes, index)
230 }
231
232 pub fn try_read_observable(control_bytes: &[u8], index: u32) -> Result<u32, PipelineError> {
239 protocol::try_read_observable(control_bytes, index).map_err(protocol_error)
240 }
241
242 #[must_use]
246 pub fn read_metrics(control_bytes: &[u8]) -> Vec<(u32, u32)> {
247 protocol::read_metrics(control_bytes)
248 }
249
250 pub fn read_metrics_into(control_bytes: &[u8], out: &mut Vec<(u32, u32)>) {
252 protocol::read_metrics_into(control_bytes, out);
253 }
254
255 pub fn try_read_metrics(control_bytes: &[u8]) -> Result<Vec<(u32, u32)>, PipelineError> {
262 protocol::try_read_metrics(control_bytes).map_err(protocol_error)
263 }
264
265 pub fn try_read_metrics_into(
272 control_bytes: &[u8],
273 out: &mut Vec<(u32, u32)>,
274 ) -> Result<(), PipelineError> {
275 protocol::try_read_metrics_into(control_bytes, out).map_err(protocol_error)
276 }
277}
278
279fn protocol_error(error: protocol::ProtocolError) -> PipelineError {
280 match error {
281 protocol::ProtocolError::ByteLengthOverflow { fix, .. } => PipelineError::QueueFull {
282 queue: "submission",
283 fix,
284 },
285 other => PipelineError::Backend(other.to_string()),
286 }
287}
288
289pub(super) fn validate_control_bytes(control_bytes: &[u8]) -> Result<(), PipelineError> {
290 let min = protocol::control_byte_len(0).ok_or_else(|| {
291 PipelineError::Backend(
292 "megakernel minimum control-buffer length overflowed usize. Fix: keep CONTROL_MIN_WORDS within host address limits."
293 .to_string(),
294 )
295 })?;
296 if control_bytes.len() < min || control_bytes.len() % 4 != 0 {
297 return Err(PipelineError::Backend(format!(
298 "megakernel control buffer has {} bytes, expected at least {min} bytes and 4-byte alignment. Fix: build it with Megakernel::encode_control.",
299 control_bytes.len()
300 )));
301 }
302 Ok(())
303}
304
305pub(super) fn validate_debug_log_bytes(debug_log_bytes: &[u8]) -> Result<(), PipelineError> {
306 let expected = protocol::debug_log_byte_len(protocol::debug::RECORD_CAPACITY)
307 .ok_or(PipelineError::QueueFull {
308 queue: "submission",
309 fix: "debug-log minimum length overflowed usize; keep debug ABI constants within host limits",
310 })?;
311 if debug_log_bytes.len() != expected {
312 return Err(PipelineError::Backend(format!(
313 "megakernel debug-log buffer has {} bytes, expected exactly {expected} bytes for {} PRINTF records. Fix: build it with Megakernel::encode_empty_debug_log(protocol::debug::RECORD_CAPACITY).",
314 debug_log_bytes.len(),
315 protocol::debug::RECORD_CAPACITY
316 )));
317 }
318 Ok(())
319}
320
321#[cfg(test)]
322mod tests;