use std::io::Read;
use std::path::Path;
use std::thread;
use embers_core::{MuxError, Result};
use tokio::io::{AsyncWriteExt, copy};
use tokio::net::UnixStream;
use tokio::sync::mpsc;
const STDIN_CHUNK: usize = 64 * 1024;
pub(crate) async fn run(socket: &Path) -> Result<()> {
let stream = UnixStream::connect(socket).await?;
let (mut from_server, mut to_server) = stream.into_split();
let mut stdin = read_stdin();
tokio::spawn(async move {
while let Some(chunk) = stdin.recv().await {
if to_server.write_all(&chunk).await.is_err() {
return;
}
}
let _ = to_server.shutdown().await;
});
let mut stdout = tokio::io::stdout();
copy(&mut from_server, &mut stdout)
.await
.map_err(|error| MuxError::transport(format!("passing on server output: {error}")))?;
stdout.flush().await?;
Ok(())
}
fn read_stdin() -> mpsc::Receiver<Vec<u8>> {
let (sender, receiver) = mpsc::channel(4);
thread::spawn(move || {
let mut stdin = std::io::stdin().lock();
let mut buffer = vec![0; STDIN_CHUNK];
loop {
match stdin.read(&mut buffer) {
Ok(0) | Err(_) => return,
Ok(read) => {
if sender.blocking_send(buffer[..read].to_vec()).is_err() {
return;
}
}
}
}
});
receiver
}