use crate::BackendError;
pub const DEFAULT_MAX_READOUT_FLOATS: usize = 1024;
pub const ENV_MAX_READOUT_FLOATS: &str = "CORPUS_IPC_ZMQ_MAX_READOUT_FLOATS";
pub fn max_readout_float_limit() -> usize {
std::env::var(ENV_MAX_READOUT_FLOATS)
.ok()
.and_then(|raw| raw.parse::<usize>().ok())
.filter(|&n| n > 0)
.unwrap_or(DEFAULT_MAX_READOUT_FLOATS)
}
pub fn parse_readout_packet(
buf: &[u8],
max_floats: usize,
) -> Result<(i64, Vec<f32>), BackendError> {
if buf.len() < 8 {
return Err(BackendError::CommunicationError(format!(
"ZMQ readout packet too short: {} bytes (need 8-byte tick header)",
buf.len()
)));
}
let payload_len = buf.len() - 8;
if payload_len % 4 != 0 {
return Err(BackendError::CommunicationError(format!(
"ZMQ readout payload misaligned: {payload_len} bytes after header (must be a multiple of 4)"
)));
}
let num_floats = payload_len / 4;
if num_floats > max_floats {
return Err(BackendError::InvalidInput(format!(
"ZMQ readout float count {num_floats} exceeds limit {max_floats}"
)));
}
let tick = i64::from_le_bytes(buf[0..8].try_into().expect("length checked"));
let mut readout = Vec::with_capacity(num_floats);
for i in 0..num_floats {
let off = 8 + i * 4;
readout.push(f32::from_le_bytes(
buf[off..off + 4].try_into().expect("aligned payload"),
));
}
Ok((tick, readout))
}