use serde::{Deserialize, Serialize};
pub const EXEC_OUTPUT_EVENT_OVERHEAD: u32 = 256;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
#[cfg_attr(feature = "ts", derive(ts_rs::TS))]
#[serde(default)]
pub struct ExecLimits {
pub max_executions: u32,
pub input_limit: u32,
pub output_limit: u32,
pub stdin_chunk_size: u32,
pub output_chunk_size: u32,
}
impl ExecLimits {
pub fn validate(&self) -> Result<(), &'static str> {
const MAX_CHUNK_SIZE: u32 = 4 * 1024 * 1024 - 1024;
if self.stdin_chunk_size > MAX_CHUNK_SIZE || self.output_chunk_size > MAX_CHUNK_SIZE {
return Err("execution chunk sizes must fit within the protocol frame ceiling");
}
if self.max_executions == 0 {
return Err("exec.max_executions must be positive");
}
if self.stdin_chunk_size == 0 || self.stdin_chunk_size > self.input_limit {
return Err("exec.stdin_chunk_size must be positive and fit within exec.input_limit");
}
let output_charge = self
.output_chunk_size
.checked_add(EXEC_OUTPUT_EVENT_OVERHEAD);
if self.output_chunk_size == 0 || output_charge.is_none_or(|n| n > self.output_limit) {
return Err(
"exec.output_chunk_size plus message overhead must fit within exec.output_limit",
);
}
Ok(())
}
}
impl Default for ExecLimits {
fn default() -> Self {
Self {
max_executions: 128,
input_limit: 64 * 1024,
output_limit: 1024 * 1024,
stdin_chunk_size: 16 * 1024,
output_chunk_size: 16 * 1024,
}
}
}