1use std::io::{self, BufRead, Read, Write};
17
18pub const MAX_FRAME: usize = 16 * 1024 * 1024;
21
22pub fn write_line<W: Write, T: serde::Serialize>(w: &mut W, value: &T) -> io::Result<()> {
28 let buf = serde_json::to_vec(value).map_err(io::Error::other)?;
29 debug_assert!(
30 !buf.contains(&b'\n'),
31 "compact JSON must not contain newlines"
32 );
33 w.write_all(&buf)?;
34 w.write_all(b"\n")?;
35 w.flush()
36}
37
38pub fn read_line<R: BufRead>(r: &mut R) -> io::Result<Option<Vec<u8>>> {
42 let mut buf = Vec::new();
43 loop {
44 let mut byte = [0u8; 1];
45 match r.read(&mut byte)? {
46 0 => {
47 return if buf.is_empty() {
49 Ok(None)
50 } else {
51 Err(io::Error::new(io::ErrorKind::UnexpectedEof, "EOF mid-line"))
52 };
53 }
54 _ => {
55 if byte[0] == b'\n' {
56 return Ok(Some(buf));
57 }
58 if buf.len() >= MAX_FRAME {
59 return Err(io::Error::new(
60 io::ErrorKind::InvalidData,
61 "line exceeds MAX_FRAME",
62 ));
63 }
64 buf.push(byte[0]);
65 }
66 }
67 }
68}
69
70pub fn write_frame<W: Write, T: serde::Serialize>(w: &mut W, value: &T) -> io::Result<()> {
74 let buf = serde_json::to_vec(value).map_err(io::Error::other)?;
75 if buf.len() > MAX_FRAME {
76 return Err(io::Error::new(
77 io::ErrorKind::InvalidData,
78 "frame exceeds MAX_FRAME",
79 ));
80 }
81 w.write_all(&(buf.len() as u32).to_be_bytes())?;
82 w.write_all(&buf)?;
83 w.flush()
84}
85
86pub fn read_frame<R: Read>(r: &mut R) -> io::Result<Option<Vec<u8>>> {
90 let mut len_buf = [0u8; 4];
91 if !read_exact_or_eof(r, &mut len_buf)? {
92 return Ok(None); }
94 let len = u32::from_be_bytes(len_buf) as usize;
95 if len > MAX_FRAME {
96 return Err(io::Error::new(
97 io::ErrorKind::InvalidData,
98 "frame length exceeds MAX_FRAME",
99 ));
100 }
101 let mut buf = vec![0u8; len];
102 r.read_exact(&mut buf)?;
103 Ok(Some(buf))
104}
105
106fn read_exact_or_eof<R: Read>(r: &mut R, buf: &mut [u8]) -> io::Result<bool> {
109 let mut filled = 0;
110 while filled < buf.len() {
111 match r.read(&mut buf[filled..])? {
112 0 => {
113 return if filled == 0 {
114 Ok(false)
115 } else {
116 Err(io::Error::new(
117 io::ErrorKind::UnexpectedEof,
118 "EOF mid-frame",
119 ))
120 };
121 }
122 n => filled += n,
123 }
124 }
125 Ok(true)
126}
127
128#[cfg(test)]
129mod tests {
130 use super::*;
131 use crate::rpc::{Id, Response};
132 use std::io::Cursor;
133
134 #[test]
135 fn line_roundtrip() {
136 let mut buf = Vec::new();
137 write_line(&mut buf, &serde_json::json!({"a": 1})).unwrap();
138 assert_eq!(buf.last(), Some(&b'\n'));
139 let mut cur = Cursor::new(buf);
140 let line = read_line(&mut cur).unwrap().unwrap();
141 let v: serde_json::Value = serde_json::from_slice(&line).unwrap();
142 assert_eq!(v["a"], 1);
143 assert!(read_line(&mut cur).unwrap().is_none());
145 }
146
147 #[test]
148 fn frame_roundtrip() {
149 let mut buf = Vec::new();
150 let resp = Response::ok(Id::Num(1), serde_json::json!({"ok": true}));
151 write_frame(&mut buf, &resp).unwrap();
152 let mut cur = Cursor::new(buf);
153 let frame = read_frame(&mut cur).unwrap().unwrap();
154 let back: Response = serde_json::from_slice(&frame).unwrap();
155 assert_eq!(back.id, Id::Num(1));
156 assert!(read_frame(&mut cur).unwrap().is_none());
157 }
158
159 #[test]
160 fn frame_with_newline_payload_survives() {
161 let mut buf = Vec::new();
163 write_frame(&mut buf, &serde_json::json!({"text": "line1\nline2"})).unwrap();
164 let mut cur = Cursor::new(buf);
165 let frame = read_frame(&mut cur).unwrap().unwrap();
166 let v: serde_json::Value = serde_json::from_slice(&frame).unwrap();
167 assert_eq!(v["text"], "line1\nline2");
168 }
169
170 #[test]
171 fn oversize_length_rejected() {
172 let mut bytes = (MAX_FRAME as u32 + 1).to_be_bytes().to_vec();
173 bytes.push(0);
174 let mut cur = Cursor::new(bytes);
175 assert!(read_frame(&mut cur).is_err());
176 }
177}