mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-27 04:19:13 +00:00
57 lines
1.5 KiB
Rust
57 lines
1.5 KiB
Rust
use std::{
|
|
io::{stdin, stdout},
|
|
thread,
|
|
};
|
|
|
|
use crossbeam_channel::{bounded, Receiver, Sender};
|
|
use lsp_types::notification::Exit;
|
|
|
|
use crate::{RawMessage, Result};
|
|
|
|
pub fn stdio_transport() -> (Receiver<RawMessage>, Sender<RawMessage>, Threads) {
|
|
let (writer_sender, writer_receiver) = bounded::<RawMessage>(16);
|
|
let writer = thread::spawn(move || {
|
|
let stdout = stdout();
|
|
let mut stdout = stdout.lock();
|
|
writer_receiver.into_iter().try_for_each(|it| it.write(&mut stdout))?;
|
|
Ok(())
|
|
});
|
|
let (reader_sender, reader_receiver) = bounded::<RawMessage>(16);
|
|
let reader = thread::spawn(move || {
|
|
let stdin = stdin();
|
|
let mut stdin = stdin.lock();
|
|
while let Some(msg) = RawMessage::read(&mut stdin)? {
|
|
let is_exit = match &msg {
|
|
RawMessage::Notification(n) => n.is::<Exit>(),
|
|
_ => false,
|
|
};
|
|
|
|
reader_sender.send(msg).unwrap();
|
|
|
|
if is_exit {
|
|
break;
|
|
}
|
|
}
|
|
Ok(())
|
|
});
|
|
let threads = Threads { reader, writer };
|
|
(reader_receiver, writer_sender, threads)
|
|
}
|
|
|
|
pub struct Threads {
|
|
reader: thread::JoinHandle<Result<()>>,
|
|
writer: thread::JoinHandle<Result<()>>,
|
|
}
|
|
|
|
impl Threads {
|
|
pub fn join(self) -> Result<()> {
|
|
match self.reader.join() {
|
|
Ok(r) => r?,
|
|
Err(_) => Err("reader panicked")?,
|
|
}
|
|
match self.writer.join() {
|
|
Ok(r) => r,
|
|
Err(_) => Err("writer panicked")?,
|
|
}
|
|
}
|
|
}
|