1 | use std::{ |
2 | io::{self, stdin, stdout}, |
3 | thread, |
4 | }; |
5 | |
6 | use log::debug; |
7 | |
8 | use crossbeam_channel::{bounded, Receiver, Sender}; |
9 | |
10 | use crate::Message; |
11 | |
12 | /// Creates an LSP connection via stdio. |
13 | pub(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 |
41 | pub(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 | |
48 | pub struct IoThreads { |
49 | reader: thread::JoinHandle<io::Result<()>>, |
50 | writer: thread::JoinHandle<io::Result<()>>, |
51 | } |
52 | |
53 | impl 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 | |