rune/languageserver/
connection.rs
1use core::fmt;
2
3use ::rust_alloc::sync::Arc;
4
5use anyhow::{anyhow, bail, Result};
6use tokio::io;
7use tokio::io::{
8 AsyncBufRead, AsyncBufReadExt as _, AsyncReadExt as _, AsyncWriteExt as _, BufReader,
9};
10use tokio::sync::Mutex;
11
12use crate::alloc::prelude::*;
13use crate::languageserver::envelope;
14
15#[derive(Debug)]
17pub(super) struct Frame<'a> {
18 pub(super) content: &'a [u8],
19}
20
21pub(super) struct Input {
23 buf: ::rust_alloc::vec::Vec<u8>,
24 stdin: BufReader<io::Stdin>,
25}
26
27impl Input {
28 pub(super) async fn next(&mut self) -> Result<Option<Frame<'_>>> {
30 let headers = match Headers::read(&mut self.buf, &mut self.stdin).await? {
31 Some(headers) => headers,
32 None => return Ok(None),
33 };
34
35 tracing::trace!("headers: {:?}", headers);
36
37 let length = match headers.content_length {
38 Some(length) => length as usize,
39 None => bail!("missing content-length"),
40 };
41
42 self.buf.resize(length, 0u8);
43 self.stdin.read_exact(&mut self.buf[..]).await?;
44 Ok(Some(Frame { content: &self.buf }))
45 }
46}
47
48#[derive(Clone)]
50pub(super) struct Output {
51 stdout: Arc<Mutex<io::Stdout>>,
52}
53
54impl Output {
55 pub(super) async fn response<R>(&self, id: Option<envelope::RequestId>, result: R) -> Result<()>
57 where
58 R: serde::Serialize,
59 {
60 let response = envelope::ResponseMessage {
61 jsonrpc: envelope::V2,
62 id,
63 result: Some(result),
64 error: None::<envelope::ResponseError<()>>,
65 };
66
67 let mut bytes = serde_json::to_vec(&response)?;
68 self.write_response(&mut bytes).await?;
69 Ok(())
70 }
71
72 pub(super) async fn method_not_found(&self, id: Option<envelope::RequestId>) -> Result<()> {
74 self.error(
75 id,
76 envelope::Code::MethodNotFound,
77 "Method not found",
78 None::<()>,
79 )
80 .await?;
81 Ok(())
82 }
83
84 pub(super) async fn error<D>(
86 &self,
87 id: Option<envelope::RequestId>,
88 code: envelope::Code,
89 message: &'static str,
90 data: Option<D>,
91 ) -> Result<()>
92 where
93 D: serde::Serialize,
94 {
95 let response = envelope::ResponseMessage {
96 jsonrpc: envelope::V2,
97 id,
98 result: None::<()>,
99 error: Some(envelope::ResponseError {
100 code,
101 message,
102 data,
103 }),
104 };
105
106 let mut bytes = serde_json::to_vec(&response)?;
107 self.write_response(&mut bytes).await?;
108 Ok(())
109 }
110
111 pub(super) async fn notification<N>(&self, notification: N::Params) -> Result<()>
113 where
114 N: lsp::notification::Notification,
115 {
116 let notification = envelope::NotificationMessage {
117 jsonrpc: envelope::V2,
118 method: N::METHOD,
119 params: notification,
120 };
121
122 let mut bytes = serde_json::to_vec(¬ification)?;
123 self.write_response(&mut bytes).await?;
124 Ok(())
125 }
126
127 pub(super) async fn log<M>(&self, typ: lsp::MessageType, message: M) -> Result<()>
129 where
130 M: fmt::Display,
131 {
132 self.notification::<lsp::notification::LogMessage>(lsp::LogMessageParams {
133 typ,
134 message: message.try_to_string()?.into_std(),
135 })
136 .await?;
137
138 Ok(())
139 }
140
141 async fn write_response(&self, bytes: &mut ::rust_alloc::vec::Vec<u8>) -> Result<()> {
143 use std::io::Write as _;
144
145 let mut m = ::rust_alloc::vec::Vec::new();
146
147 write!(m, "Content-Length: {}\r\n", bytes.len())?;
148 write!(m, "\r\n")?;
149 m.append(bytes);
150
151 let mut stdout = self.stdout.lock().await;
152 stdout.write_all(&m).await?;
153 stdout.flush().await?;
154 Ok(())
155 }
156}
157
158pub(super) fn stdio() -> Result<(Input, Output)> {
160 let stdin = io::stdin();
161 let stdout = io::stdout();
162
163 let input = Input {
164 buf: ::rust_alloc::vec::Vec::new(),
165 stdin: BufReader::new(stdin),
166 };
167
168 let output = Output {
169 stdout: Arc::new(Mutex::new(stdout)),
170 };
171
172 Ok((input, output))
173}
174
175#[derive(Debug)]
176pub(super) enum ContentType {
177 JsonRPC,
178}
179
180#[derive(Default, Debug)]
181pub(super) struct Headers {
182 pub(super) content_length: Option<u32>,
183 pub(super) content_type: Option<ContentType>,
184}
185
186impl Headers {
187 pub(super) async fn read<S>(
189 buf: &mut ::rust_alloc::vec::Vec<u8>,
190 reader: &mut S,
191 ) -> anyhow::Result<Option<Self>>
192 where
193 S: Unpin + AsyncBufRead,
194 {
195 let mut headers = Headers::default();
196
197 loop {
198 buf.clear();
199
200 let len = match reader.read_until(b'\n', buf).await {
201 Ok(len) => len,
202 Err(error) => return Err(error.into()),
203 };
204
205 if len == 0 {
206 return Ok(None);
207 }
208
209 debug_assert!(len == buf.len());
210 let buf = &buf[..len];
211
212 let buf = std::str::from_utf8(buf)?;
213 let line = buf.trim();
214
215 if line.is_empty() {
216 break;
217 }
218
219 let Some((key, value)) = line.split_once(':') else {
220 return Err(anyhow!("bad header"));
221 };
222
223 let key = key.trim();
224 let value = value.trim();
225 let key = key.to_lowercase();
226
227 match key.as_str() {
228 "content-type" => match value {
229 "application/vscode-jsonrpc; charset=utf-8" => {
230 headers.content_type = Some(ContentType::JsonRPC);
231 }
232 value => {
233 return Err(anyhow!("bad value: {:?}", value));
234 }
235 },
236 "content-length" => {
237 let value = value
238 .parse::<u32>()
239 .map_err(|e| anyhow!("bad content-length: {}: {}", value, e))?;
240
241 headers.content_length = Some(value);
242 }
243 key => {
244 return Err(anyhow!("header not supported: {:?}", key));
245 }
246 }
247 }
248
249 Ok(Some(headers))
250 }
251}