chromiumoxide/
async_process.rsuse ::tokio::process;
use std::ffi::OsStr;
use std::pin::Pin;
pub use std::process::{ExitStatus, Stdio};
use std::task::{Context, Poll};
#[derive(Debug)]
pub struct Command {
inner: process::Command,
}
impl Command {
pub fn new<S: AsRef<OsStr>>(program: S) -> Self {
let mut inner = process::Command::new(program);
inner.kill_on_drop(true);
Self { inner }
}
pub fn arg<S: AsRef<OsStr>>(&mut self, arg: S) -> &mut Self {
self.inner.arg(arg);
self
}
pub fn args<I, S>(&mut self, args: I) -> &mut Self
where
I: IntoIterator<Item = S>,
S: AsRef<OsStr>,
{
self.inner.args(args);
self
}
pub fn envs<I, K, V>(&mut self, vars: I) -> &mut Self
where
I: IntoIterator<Item = (K, V)>,
K: AsRef<OsStr>,
V: AsRef<OsStr>,
{
self.inner.envs(vars);
self
}
pub fn stderr<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Self {
self.inner.stderr(cfg);
self
}
pub fn spawn(&mut self) -> std::io::Result<Child> {
let inner = self.inner.spawn()?;
Ok(Child::new(inner))
}
}
#[derive(Debug)]
pub struct Child {
pub stderr: Option<ChildStderr>,
pub inner: process::Child,
}
impl Child {
fn new(mut inner: process::Child) -> Self {
let stderr = inner.stderr.take();
Self {
inner,
stderr: stderr.map(|inner| ChildStderr { inner }),
}
}
pub async fn kill(&mut self) -> std::io::Result<()> {
self.inner.kill().await
}
pub async fn wait(&mut self) -> std::io::Result<ExitStatus> {
self.inner.wait().await
}
pub fn try_wait(&mut self) -> std::io::Result<Option<ExitStatus>> {
self.inner.try_wait()
}
pub fn as_mut_inner(&mut self) -> &mut process::Child {
&mut self.inner
}
pub fn into_inner(self) -> process::Child {
let mut inner = self.inner;
inner.stderr = self.stderr.map(ChildStderr::into_inner);
inner
}
}
#[derive(Debug)]
pub struct ChildStderr {
pub inner: process::ChildStderr,
}
impl ChildStderr {
pub fn into_inner(self) -> process::ChildStderr {
self.inner
}
}
impl futures::AsyncRead for ChildStderr {
fn poll_read(
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &mut [u8],
) -> Poll<std::io::Result<usize>> {
let mut buf = tokio::io::ReadBuf::new(buf);
futures::ready!(tokio::io::AsyncRead::poll_read(
Pin::new(&mut self.inner),
cx,
&mut buf
))?;
Poll::Ready(Ok(buf.filled().len()))
}
}