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, Receiver, IoThreads) { let (reader_receiver, reader) = make_reader(stream.try_clone().unwrap()); let (writer_sender, writer, messages_to_drop) = make_write(stream); let io_threads = make_io_threads(reader, writer); (writer_sender, reader_receiver, io_threads) } fn make_reader(stream: TcpStream) -> (Receiver, thread::JoinHandle>) { let (reader_sender, reader_receiver) = bounded::(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, thread::JoinHandle>, Receiver) { let (writer_sender, writer_receiver) = bounded::(0); let (drop_sender, drop_receiver) = bounded::(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) }