vtcode_desktop_protocol/
frames.rs1use std::io;
3
4use serde::Serialize;
5use tokio::io::{AsyncBufRead, AsyncBufReadExt, AsyncWrite, AsyncWriteExt};
6
7use super::{MAX_FRAME_BYTES, ProtocolError};
8
9pub async fn read_frame<R>(reader: &mut R) -> io::Result<Option<Vec<u8>>>
11where
12 R: AsyncBufRead + Unpin,
13{
14 let mut frame = Vec::with_capacity(1024);
15 loop {
16 let available = reader.fill_buf().await?;
17 if available.is_empty() {
18 return if frame.is_empty() { Ok(None) } else { Ok(Some(frame)) };
19 }
20
21 let newline = available.iter().position(|byte| *byte == b'\n');
22 let take = newline.map_or(available.len(), |index| index + 1);
23 let content_end = if newline.is_some() && available.get(take.saturating_sub(1)) == Some(&b'\n') {
24 take.saturating_sub(1)
25 } else {
26 take
27 };
28 let content_end = if content_end > 0 && available.get(content_end.saturating_sub(1)) == Some(&b'\r') {
29 content_end.saturating_sub(1)
30 } else {
31 content_end
32 };
33
34 if frame.len().saturating_add(content_end) > MAX_FRAME_BYTES {
35 reader.consume(take);
36 return Err(io::Error::new(
37 io::ErrorKind::InvalidData,
38 ProtocolError::FrameTooLarge { limit: MAX_FRAME_BYTES },
39 ));
40 }
41 let content = available
42 .get(..content_end)
43 .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "invalid buffered frame boundary"))?;
44 frame.extend_from_slice(content);
45 reader.consume(take);
46
47 if newline.is_some() {
48 return Ok(Some(frame));
49 }
50 }
51}
52
53pub async fn write_frame<W, T>(writer: &mut W, message: &T) -> io::Result<()>
55where
56 W: AsyncWrite + Unpin,
57 T: Serialize,
58{
59 let encoded = serde_json::to_vec(message).map_err(io::Error::other)?;
60 if encoded.len() > MAX_FRAME_BYTES {
61 return Err(io::Error::new(
62 io::ErrorKind::InvalidData,
63 ProtocolError::FrameTooLarge { limit: MAX_FRAME_BYTES },
64 ));
65 }
66 writer.write_all(&encoded).await?;
67 writer.write_all(b"\n").await?;
68 writer.flush().await
69}