1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
use std::{ io::{stdin, stdout}, thread, }; use crossbeam_channel::{bounded, Receiver, Sender}; use failure::bail; 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(_) => bail!("reader panicked"), } match self.writer.join() { Ok(r) => r, Err(_) => bail!("writer panicked"), } } }