Skip to content

Commit 4284804

Browse files
committed
add postcard related methods to proc-macro-apo
1 parent 83edf8f commit 4284804

File tree

8 files changed

+146
-6
lines changed

8 files changed

+146
-6
lines changed

src/tools/rust-analyzer/Cargo.lock

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -560,6 +560,18 @@ version = "1.15.0"
560560
source = "registry+https://github.com/rust-lang/crates.io-index"
561561
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
562562

563+
[[package]]
564+
name = "embedded-io"
565+
version = "0.4.0"
566+
source = "registry+https://github.com/rust-lang/crates.io-index"
567+
checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced"
568+
569+
[[package]]
570+
name = "embedded-io"
571+
version = "0.6.1"
572+
source = "registry+https://github.com/rust-lang/crates.io-index"
573+
checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d"
574+
563575
[[package]]
564576
name = "ena"
565577
version = "0.14.3"
@@ -1785,6 +1797,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
17851797
checksum = "6764c3b5dd454e283a30e6dfe78e9b31096d9e32036b5d1eaac7a6119ccb9a24"
17861798
dependencies = [
17871799
"cobs",
1800+
"embedded-io 0.4.0",
1801+
"embedded-io 0.6.1",
17881802
"heapless",
17891803
"serde",
17901804
]
@@ -1820,6 +1834,7 @@ dependencies = [
18201834
"indexmap",
18211835
"intern",
18221836
"paths",
1837+
"postcard",
18231838
"proc-macro-srv",
18241839
"rustc-hash 2.1.1",
18251840
"serde",

src/tools/rust-analyzer/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ object = { version = "0.36.7", default-features = false, features = [
127127
"macho",
128128
"pe",
129129
] }
130+
postcard = {version = "1.1.3", features = ["alloc"]}
130131
process-wrap = { version = "8.2.1", features = ["std"] }
131132
pulldown-cmark-to-cmark = "10.0.4"
132133
pulldown-cmark = { version = "0.9.6", default-features = false }

src/tools/rust-analyzer/crates/proc-macro-api/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ proc-macro-srv = {workspace = true, optional = true}
2929
span = { path = "../span", version = "0.0.0", default-features = false}
3030

3131
intern.workspace = true
32+
postcard.workspace = true
3233

3334
[features]
3435
sysroot-abi = ["proc-macro-srv", "proc-macro-srv/sysroot-abi"]

src/tools/rust-analyzer/crates/proc-macro-api/src/legacy_protocol.rs

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
33
pub mod json;
44
pub mod msg;
5+
pub mod postcard_wire;
56

67
use std::{
78
io::{BufRead, Write},
@@ -151,7 +152,11 @@ fn send_task(srv: &ProcMacroServerProcess, req: Request) -> Result<Response, Ser
151152
return Err(server_error.clone());
152153
}
153154

154-
srv.send_task(send_request, req)
155+
if srv.use_postcard() {
156+
srv.send_task_bin(send_request_postcard, req)
157+
} else {
158+
srv.send_task(send_request, req)
159+
}
155160
}
156161

157162
/// Sends a request to the server and reads the response.
@@ -171,3 +176,34 @@ fn send_request(
171176
})?;
172177
Ok(res)
173178
}
179+
180+
fn send_request_postcard(
181+
mut writer: &mut dyn Write,
182+
mut reader: &mut dyn BufRead,
183+
req: Request,
184+
buf: &mut Vec<u8>,
185+
) -> Result<Option<Response>, ServerError> {
186+
let bytes = postcard_wire::encode_cobs(&req)
187+
.map_err(|_| ServerError { message: "failed to write request".into(), io: None })?;
188+
189+
postcard_wire::write_postcard(&mut writer, &bytes).map_err(|err| ServerError {
190+
message: "failed to write request".into(),
191+
io: Some(Arc::new(err)),
192+
})?;
193+
194+
let frame = postcard_wire::read_postcard(&mut reader, buf).map_err(|err| ServerError {
195+
message: "failed to read response".into(),
196+
io: Some(Arc::new(err)),
197+
})?;
198+
199+
match frame {
200+
None => Ok(None),
201+
Some(bytes) => {
202+
let resp: Response = postcard_wire::decode_cobs(bytes).map_err(|e| ServerError {
203+
message: format!("failed to decode message: {e}"),
204+
io: None,
205+
})?;
206+
Ok(Some(resp))
207+
}
208+
}
209+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
//! Postcard encode and decode implementations.
2+
3+
use std::io::{self, BufRead, Write};
4+
5+
pub fn read_postcard<'a>(
6+
input: &mut impl BufRead,
7+
buf: &'a mut Vec<u8>,
8+
) -> io::Result<Option<&'a mut [u8]>> {
9+
buf.clear();
10+
let n = input.read_until(0, buf)?;
11+
if n == 0 {
12+
return Ok(None);
13+
}
14+
Ok(Some(&mut buf[..]))
15+
}
16+
pub fn write_postcard(out: &mut impl Write, msg: &[u8]) -> io::Result<()> {
17+
out.write_all(msg)?;
18+
out.flush()
19+
}
20+
21+
pub fn encode_cobs<T: serde::Serialize>(value: &T) -> Result<Vec<u8>, postcard::Error> {
22+
postcard::to_allocvec_cobs(value)
23+
}
24+
25+
pub fn decode_cobs<T: serde::de::DeserializeOwned>(bytes: &mut [u8]) -> Result<T, postcard::Error> {
26+
postcard::from_bytes_cobs(bytes)
27+
}

src/tools/rust-analyzer/crates/proc-macro-api/src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,10 @@ pub mod version {
3131
/// Whether literals encode their kind as an additional u32 field and idents their rawness as a u32 field.
3232
pub const EXTENDED_LEAF_DATA: u32 = 5;
3333
pub const HASHED_AST_ID: u32 = 6;
34+
pub const POSTCARD_WIRE: u32 = 7;
3435

3536
/// Current API version of the proc-macro protocol.
36-
pub const CURRENT_API_VERSION: u32 = HASHED_AST_ID;
37+
pub const CURRENT_API_VERSION: u32 = POSTCARD_WIRE;
3738
}
3839

3940
/// Represents different kinds of procedural macros that can be expanded by the external server.

src/tools/rust-analyzer/crates/proc-macro-api/src/process.rs

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ pub(crate) struct ProcMacroServerProcess {
3131
#[derive(Debug)]
3232
enum Protocol {
3333
LegacyJson { mode: SpanMode },
34+
Postcard { mode: SpanMode },
3435
}
3536

3637
/// Maintains the state of the proc-macro server process.
@@ -82,7 +83,11 @@ impl ProcMacroServerProcess {
8283
if srv.version >= version::RUST_ANALYZER_SPAN_SUPPORT
8384
&& let Ok(mode) = srv.enable_rust_analyzer_spans()
8485
{
85-
srv.protocol = Protocol::LegacyJson { mode };
86+
if srv.version >= version::POSTCARD_WIRE {
87+
srv.protocol = Protocol::Postcard { mode };
88+
} else {
89+
srv.protocol = Protocol::LegacyJson { mode };
90+
}
8691
}
8792
tracing::info!("Proc-macro server protocol: {:?}", srv.protocol);
8893
Ok(srv)
@@ -99,6 +104,10 @@ impl ProcMacroServerProcess {
99104
self.exited.get().map(|it| &it.0)
100105
}
101106

107+
pub(crate) fn use_postcard(&self) -> bool {
108+
matches!(self.protocol, Protocol::Postcard { .. })
109+
}
110+
102111
/// Retrieves the API version of the proc-macro server.
103112
pub(crate) fn version(&self) -> u32 {
104113
self.version
@@ -108,20 +117,23 @@ impl ProcMacroServerProcess {
108117
pub(crate) fn rust_analyzer_spans(&self) -> bool {
109118
match self.protocol {
110119
Protocol::LegacyJson { mode } => mode == SpanMode::RustAnalyzer,
120+
Protocol::Postcard { mode } => mode == SpanMode::RustAnalyzer,
111121
}
112122
}
113123

114124
/// Checks the API version of the running proc-macro server.
115125
fn version_check(&self) -> Result<u32, ServerError> {
116126
match self.protocol {
117127
Protocol::LegacyJson { .. } => legacy_protocol::version_check(self),
128+
Protocol::Postcard { .. } => legacy_protocol::version_check(self),
118129
}
119130
}
120131

121132
/// Enable support for rust-analyzer span mode if the server supports it.
122133
fn enable_rust_analyzer_spans(&self) -> Result<SpanMode, ServerError> {
123134
match self.protocol {
124135
Protocol::LegacyJson { .. } => legacy_protocol::enable_rust_analyzer_spans(self),
136+
Protocol::Postcard { .. } => legacy_protocol::enable_rust_analyzer_spans(self),
125137
}
126138
}
127139

@@ -132,6 +144,7 @@ impl ProcMacroServerProcess {
132144
) -> Result<Result<Vec<(String, ProcMacroKind)>, String>, ServerError> {
133145
match self.protocol {
134146
Protocol::LegacyJson { .. } => legacy_protocol::find_proc_macros(self, dylib_path),
147+
Protocol::Postcard { .. } => legacy_protocol::find_proc_macros(self, dylib_path),
135148
}
136149
}
137150

@@ -188,6 +201,55 @@ impl ProcMacroServerProcess {
188201
}
189202
})
190203
}
204+
205+
pub(crate) fn send_task_bin<Request, Response>(
206+
&self,
207+
serialize_req: impl FnOnce(
208+
&mut dyn Write,
209+
&mut dyn BufRead,
210+
Request,
211+
&mut Vec<u8>,
212+
) -> Result<Option<Response>, ServerError>,
213+
req: Request,
214+
) -> Result<Response, ServerError> {
215+
let state = &mut *self.state.lock().unwrap();
216+
let mut buf = Vec::<u8>::new();
217+
serialize_req(&mut state.stdin, &mut state.stdout, req, &mut buf)
218+
.and_then(|res| {
219+
res.ok_or_else(|| ServerError {
220+
message: "proc-macro server did not respond with data".to_owned(),
221+
io: Some(Arc::new(io::Error::new(
222+
io::ErrorKind::BrokenPipe,
223+
"proc-macro server did not respond with data",
224+
))),
225+
})
226+
})
227+
.map_err(|e| {
228+
if e.io.as_ref().map(|it| it.kind()) == Some(io::ErrorKind::BrokenPipe) {
229+
match state.process.child.try_wait() {
230+
Ok(None) | Err(_) => e,
231+
Ok(Some(status)) => {
232+
let mut msg = String::new();
233+
if !status.success()
234+
&& let Some(stderr) = state.process.child.stderr.as_mut()
235+
{
236+
_ = stderr.read_to_string(&mut msg);
237+
}
238+
let server_error = ServerError {
239+
message: format!(
240+
"proc-macro server exited with {status}{}{msg}",
241+
if msg.is_empty() { "" } else { ": " }
242+
),
243+
io: None,
244+
};
245+
self.exited.get_or_init(|| AssertUnwindSafe(server_error)).0.clone()
246+
}
247+
}
248+
} else {
249+
e
250+
}
251+
})
252+
}
191253
}
192254

193255
/// Manages the execution of the proc-macro server process.

src/tools/rust-analyzer/crates/proc-macro-srv-cli/src/main_loop.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -200,8 +200,6 @@ fn run_postcard() -> io::Result<()> {
200200
thread::sleep(std::time::Duration::from_secs(1));
201201
continue;
202202
};
203-
dbg!(&req);
204-
205203
let res = match req {
206204
msg::Request::ListMacros { dylib_path } => {
207205
msg::Response::ListMacros(srv.list_macros(&dylib_path).map(|macros| {
@@ -304,7 +302,6 @@ fn run_postcard() -> io::Result<()> {
304302
}
305303
};
306304

307-
dbg!(&res);
308305
let res = postcard_wire::encode_cobs(&res).unwrap();
309306
postcard_wire::write_postcard(&mut writer, &res)?;
310307
}

0 commit comments

Comments
 (0)