travsr_plugin_protocol/
codec.rs1use std::io::{self, Read, Write};
2
3pub fn encode_message<T: serde::Serialize>(msg: &T) -> io::Result<Vec<u8>> {
4 let payload =
5 serde_json::to_vec(msg).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
6 let len = u32::try_from(payload.len())
7 .map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "payload too large"))?;
8 let mut frame = Vec::with_capacity(4 + payload.len());
9 frame.extend_from_slice(&len.to_be_bytes());
10 frame.extend_from_slice(&payload);
11 Ok(frame)
12}
13
14pub fn decode_message<T: serde::de::DeserializeOwned>(reader: &mut impl Read) -> io::Result<T> {
15 let mut len_buf = [0u8; 4];
16 reader.read_exact(&mut len_buf)?;
17 let len = u32::from_be_bytes(len_buf) as usize;
18 let mut payload = vec![0u8; len];
19 reader.read_exact(&mut payload)?;
20 serde_json::from_slice(&payload).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
21}
22
23pub fn write_message<T: serde::Serialize>(writer: &mut impl Write, msg: &T) -> io::Result<()> {
24 let frame = encode_message(msg)?;
25 writer.write_all(&frame)?;
26 writer.flush()
27}
28
29#[cfg(test)]
30mod tests {
31 use super::*;
32 use crate::types::ParseRequest;
33 use std::io::Cursor;
34 use std::path::PathBuf;
35
36 #[test]
37 fn round_trip_parse_request() {
38 let req = ParseRequest {
39 path: PathBuf::from("src/main.ts"),
40 vname_path: "src/main.ts".into(),
41 corpus: "github.com/acme/foo".into(),
42 package: "acme".into(),
43 source: None,
44 };
45 let payload = serde_json::to_vec(&req).unwrap();
46 let encoded = encode_message(&req).unwrap();
47 assert_eq!(encoded.len(), 4 + payload.len());
49 let len = u32::from_be_bytes(encoded[..4].try_into().unwrap()) as usize;
51 assert_eq!(len, payload.len());
52 let mut cursor = Cursor::new(&encoded);
53 let decoded: ParseRequest = decode_message(&mut cursor).unwrap();
54 assert_eq!(decoded.path, req.path);
55 assert_eq!(decoded.vname_path, req.vname_path);
56 assert_eq!(decoded.corpus, req.corpus);
57 }
58}