lsp_server/
socket.rs
use std::{
io::{self, BufReader},
net::TcpStream,
thread,
};
use crossbeam_channel::{Receiver, Sender, bounded};
use crate::{
Message,
stdio::{IoThreads, make_io_threads},
};
pub(crate) fn socket_transport(
stream: TcpStream,
) -> (Sender<Message>, Receiver<Message>, IoThreads) {
let (reader_receiver, reader) = make_reader(stream.try_clone().unwrap());
let (writer_sender, writer, messages_to_drop) = make_write(stream);
let dropper = std::thread::spawn(move || {
messages_to_drop.into_iter().for_each(drop);
});
let io_threads = make_io_threads(reader, writer, dropper);
(writer_sender, reader_receiver, io_threads)
}
fn make_reader(stream: TcpStream) -> (Receiver<Message>, thread::JoinHandle<io::Result<()>>) {
let (reader_sender, reader_receiver) = bounded::<Message>(0);
let reader = thread::spawn(move || {
let mut buf_read = BufReader::new(stream);
while let Some(msg) = Message::read(&mut buf_read).unwrap() {
let is_exit = matches!(&msg, Message::Notification(n) if n.is_exit());
reader_sender.send(msg).unwrap();
if is_exit {
break;
}
}
Ok(())
});
(reader_receiver, reader)
}
fn make_write(
mut stream: TcpStream,
) -> (Sender<Message>, thread::JoinHandle<io::Result<()>>, Receiver<Message>) {
let (writer_sender, writer_receiver) = bounded::<Message>(0);
let (drop_sender, drop_receiver) = bounded::<Message>(0);
let writer = thread::spawn(move || {
writer_receiver
.into_iter()
.try_for_each(|it| {
let result = it.write(&mut stream);
let _ = drop_sender.send(it);
result
})
.unwrap();
Ok(())
});
(writer_sender, writer, drop_receiver)
}