1use std::io;
11use tokio::io::{AsyncBufRead, AsyncBufReadExt, AsyncReadExt, AsyncWrite, AsyncWriteExt};
12
13use crate::common::Error;
14
15pub async fn read_message<R: AsyncBufRead + Unpin>(reader: &mut R) -> Result<String, Error> {
19 let mut content_length: Option<usize> = None;
21
22 loop {
23 let mut line = String::new();
24 let bytes_read = reader.read_line(&mut line).await.map_err(|e| {
25 if e.kind() == io::ErrorKind::UnexpectedEof {
26 Error::AdapterCrashed
27 } else {
28 Error::Io(e)
29 }
30 })?;
31
32 if bytes_read == 0 {
33 return Err(Error::AdapterCrashed);
34 }
35
36 if line == "\r\n" || line == "\n" {
38 break;
39 }
40
41 let line = line.trim();
43 if let Some(value) = line.strip_prefix("Content-Length:") {
44 content_length = Some(value.trim().parse().map_err(|_| {
45 Error::DapProtocol(format!("Invalid Content-Length: {}", value.trim()))
46 })?);
47 }
48 }
50
51 let len = content_length.ok_or_else(|| {
52 Error::DapProtocol("Missing Content-Length header".to_string())
53 })?;
54
55 if len > 100 * 1024 * 1024 {
57 return Err(Error::DapProtocol(format!(
58 "Content-Length too large: {} bytes",
59 len
60 )));
61 }
62
63 let mut body = vec![0u8; len];
65 reader.read_exact(&mut body).await.map_err(|e| {
66 if e.kind() == io::ErrorKind::UnexpectedEof {
67 Error::AdapterCrashed
68 } else {
69 Error::Io(e)
70 }
71 })?;
72
73 String::from_utf8(body).map_err(|e| Error::DapProtocol(format!("Invalid UTF-8: {}", e)))
74}
75
76pub async fn write_message<W: AsyncWrite + Unpin>(
80 writer: &mut W,
81 json: &str,
82) -> Result<(), Error> {
83 let header = format!("Content-Length: {}\r\n\r\n", json.len());
84
85 writer.write_all(header.as_bytes()).await?;
86 writer.write_all(json.as_bytes()).await?;
87 writer.flush().await?;
88
89 Ok(())
90}
91
92#[cfg(test)]
93mod tests {
94 use super::*;
95 use std::io::Cursor;
96 use tokio::io::BufReader;
97
98 #[tokio::test]
99 async fn test_read_message() {
100 let data = b"Content-Length: 13\r\n\r\n{\"test\":true}";
101 let mut reader = BufReader::new(Cursor::new(data.to_vec()));
102
103 let result = read_message(&mut reader).await.unwrap();
104 assert_eq!(result, "{\"test\":true}");
105 }
106
107 #[tokio::test]
108 async fn test_read_message_with_extra_headers() {
109 let data = b"Content-Length: 13\r\nContent-Type: application/json\r\n\r\n{\"test\":true}";
110 let mut reader = BufReader::new(Cursor::new(data.to_vec()));
111
112 let result = read_message(&mut reader).await.unwrap();
113 assert_eq!(result, "{\"test\":true}");
114 }
115
116 #[tokio::test]
117 async fn test_write_message() {
118 let mut output = Vec::new();
119 write_message(&mut output, "{\"test\":true}").await.unwrap();
120
121 let expected = "Content-Length: 13\r\n\r\n{\"test\":true}";
122 assert_eq!(String::from_utf8(output).unwrap(), expected);
123 }
124}