use crate::error::ProtoError;
use serde::{Serialize, de::DeserializeOwned};
use std::io::{BufRead, Write};
pub const MAX_FRAME_BYTES: usize = 64 << 20;
pub fn read_frame<R: BufRead, T: DeserializeOwned>(
reader: &mut R,
) -> Result<Option<T>, ProtoError> {
let mut buf: Vec<u8> = Vec::with_capacity(512);
loop {
let chunk = reader.fill_buf()?;
if chunk.is_empty() {
if buf.is_empty() {
return Ok(None);
}
return parse(&buf).map(Some);
}
if let Some(nl_idx) = chunk.iter().position(|&b| b == b'\n') {
if buf.len() + nl_idx > MAX_FRAME_BYTES {
return Err(ProtoError::FrameTooLarge);
}
buf.extend_from_slice(&chunk[..nl_idx]);
reader.consume(nl_idx + 1);
return parse(&buf).map(Some);
}
if buf.len() + chunk.len() > MAX_FRAME_BYTES {
return Err(ProtoError::FrameTooLarge);
}
buf.extend_from_slice(chunk);
let n = chunk.len();
reader.consume(n);
}
}
fn parse<T: DeserializeOwned>(bytes: &[u8]) -> Result<T, ProtoError> {
serde_json::from_slice(bytes).map_err(ProtoError::Decode)
}
pub fn write_frame<W: Write, T: Serialize>(writer: &mut W, frame: &T) -> Result<(), ProtoError> {
let bytes = serde_json::to_vec(frame)?;
if bytes.len() >= MAX_FRAME_BYTES {
return Err(ProtoError::FrameTooLarge);
}
writer.write_all(&bytes)?;
writer.write_all(b"\n")?;
Ok(())
}