blob: 2485e3713e2dcf0a0593058f22a975c3e5f3d530 [file] [log] [blame] [edit]
use std::io;
use std::pin::Pin;
use std::process::{Command, Stdio};
use std::rc::Rc;
use std::task::{Context, Poll};
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
pub struct ChildProcess {
stdin: tokio::process::ChildStdin,
stdout: tokio::process::ChildStdout,
child: Rc<tokio::process::Child>,
}
impl AsyncRead for ChildProcess {
fn poll_read(
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &mut ReadBuf<'_>,
) -> Poll<io::Result<()>> {
Pin::new(&mut self.stdout).poll_read(cx, buf)
}
}
impl AsyncWrite for ChildProcess {
fn poll_write(
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &[u8],
) -> Poll<io::Result<usize>> {
Pin::new(&mut self.stdin).poll_write(cx, buf)
}
fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
Pin::new(&mut self.stdin).poll_flush(cx)
}
fn poll_shutdown(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
Pin::new(&mut self.stdin).poll_shutdown(cx)
}
}
impl ChildProcess {
pub fn spawn_from_command(mut cmd: Command) -> Result<ChildProcess, std::io::Error> {
cmd.stdin(Stdio::piped());
cmd.stdout(Stdio::piped());
let mut child = tokio::process::Command::from(cmd).spawn().expect("to async spawn process");
Ok(ChildProcess {
stdout: child.stdout.take().unwrap(),
stdin: child.stdin.take().unwrap(),
child: Rc::new(child),
})
}
/// Returns a handle to the underlying `Child` process.
/// Useful when waiting until child process exits.
pub fn child(&self) -> Rc<tokio::process::Child> {
Rc::clone(&self.child)
}
}