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