ra_ap_lsp_server/
stdio.rs

1use std::{
2    io::{self, stdin, stdout},
3    thread,
4};
5
6use crossbeam_channel::{bounded, Receiver, Sender};
7
8use crate::Message;
9
10/// Creates an LSP connection via stdio.
11pub(crate) fn stdio_transport() -> (Sender<Message>, Receiver<Message>, IoThreads) {
12    let (writer_sender, writer_receiver) = bounded::<Message>(0);
13    let writer = thread::spawn(move || {
14        let stdout = stdout();
15        let mut stdout = stdout.lock();
16        writer_receiver.into_iter().try_for_each(|it| it.write(&mut stdout))?;
17        Ok(())
18    });
19    let (reader_sender, reader_receiver) = bounded::<Message>(0);
20    let reader = thread::spawn(move || {
21        let stdin = stdin();
22        let mut stdin = stdin.lock();
23        while let Some(msg) = Message::read(&mut stdin)? {
24            let is_exit = match &msg {
25                Message::Notification(n) => n.is_exit(),
26                _ => false,
27            };
28
29            reader_sender.send(msg).unwrap();
30
31            if is_exit {
32                break;
33            }
34        }
35        Ok(())
36    });
37    let threads = IoThreads { reader, writer };
38    (writer_sender, reader_receiver, threads)
39}
40
41// Creates an IoThreads
42pub(crate) fn make_io_threads(
43    reader: thread::JoinHandle<io::Result<()>>,
44    writer: thread::JoinHandle<io::Result<()>>,
45) -> IoThreads {
46    IoThreads { reader, writer }
47}
48
49pub struct IoThreads {
50    reader: thread::JoinHandle<io::Result<()>>,
51    writer: thread::JoinHandle<io::Result<()>>,
52}
53
54impl IoThreads {
55    pub fn join(self) -> io::Result<()> {
56        match self.reader.join() {
57            Ok(r) => r?,
58            Err(err) => {
59                println!("reader panicked!");
60                std::panic::panic_any(err)
61            }
62        }
63        match self.writer.join() {
64            Ok(r) => r,
65            Err(err) => {
66                println!("writer panicked!");
67                std::panic::panic_any(err);
68            }
69        }
70    }
71}