1use bytes::{Buf, BytesMut};
2use lsp_ty::{NotificationMessage, OneOf3, RequestMessage, ResponseMessage};
3
4use super::BUF_SIZE;
5
6fn parse_header(headers: &str) -> Result<(String, usize), String> {
7 let mut segs = headers.split(':');
8 let key = segs.next().unwrap();
9 let mut content_type = String::new();
10 let mut content_length = 0;
11 if key == "Content-Length" {
12 content_length = segs.next().unwrap().trim().parse().unwrap();
13 } else if key == "Content-Type" {
14 content_type = segs.next().unwrap().trim().to_string();
15 } else {
16 tracing::error!("unknown header {}", key);
17 }
18 if content_length == 0 {
19 let msg = "empty content length or missing Content-Length header";
20 tracing::error!(msg);
21 return Err(msg.to_string());
22 }
23 Ok((content_type, content_length))
24}
25
26#[derive(Debug, Clone)]
27pub struct CodecState {
28 pub content_type: String,
29 pub read_content_length: usize,
30 pub read_buf: [u8; BUF_SIZE],
31 pub read_data: BytesMut,
32}
33
34impl CodecState {
35 pub fn consume_body(
36 &mut self,
37 ) -> serde_json::Result<OneOf3<RequestMessage, ResponseMessage, NotificationMessage>> {
38 let msg = serde_json::from_slice(&self.read_data[..self.read_content_length])?;
39 self.read_data.advance(self.read_content_length);
41 self.read_content_length = 0;
42 Ok(msg)
43 }
44
45 pub fn parse_header(&mut self, headers: String) -> Result<(), String> {
46 let (content_type, content_length) = parse_header(&headers)?;
47 self.content_type = content_type;
48 self.read_content_length = content_length;
49 Ok(())
50 }
51
52 fn header_pos(&self) -> Option<usize> {
53 self.read_data
54 .windows(4)
55 .position(|s| s == [b'\r', b'\n', b'\r', b'\n'])
56 }
57
58 pub fn try_parse_header(&mut self) -> Option<Result<(), String>> {
59 self.header_pos().map(|stop_at| {
60 let headers = String::from_utf8(self.read_data[..stop_at].to_vec()).unwrap();
61 self.read_data.advance(stop_at + 4);
62 self.parse_header(headers)
63 })
64 }
65
66 pub fn body_ready(&self) -> bool {
67 self.read_content_length <= self.read_data.len()
68 }
69}
70
71impl Default for CodecState {
72 fn default() -> Self {
73 Self {
74 content_type: "application/vscode-jsonrpc; charset=utf-8".to_string(),
75 read_content_length: Default::default(),
76 read_buf: [0; BUF_SIZE],
77 read_data: BytesMut::with_capacity(BUF_SIZE),
78 }
79 }
80}