byor 1.0.0

Bring your own runtime!
Documentation
use crate::process::*;
use std::{
    ffi::OsStr,
    io::Result,
    process::{ExitStatus, Output, Stdio},
};
use tokio::process::{ChildStderr, ChildStdin, ChildStdout};
use tokio_util::compat::{
    Compat, TokioAsyncReadCompatExt as ReadCompat, TokioAsyncWriteCompatExt as WriteCompat,
};

impl Command for tokio::process::Command {
    type Child = tokio::process::Child;

    fn new(program: impl AsRef<OsStr>) -> Self {
        tokio::process::Command::new(program)
    }

    fn arg(&mut self, arg: impl AsRef<OsStr>) -> &mut Self {
        self.arg(arg)
    }

    fn args(&mut self, args: impl IntoIterator<Item = impl AsRef<OsStr>>) -> &mut Self {
        self.args(args)
    }

    fn env(&mut self, key: impl AsRef<OsStr>, val: impl AsRef<std::ffi::OsStr>) -> &mut Self {
        self.env(key, val)
    }

    fn envs(
        &mut self,
        vars: impl IntoIterator<Item = (impl AsRef<OsStr>, impl AsRef<std::ffi::OsStr>)>,
    ) -> &mut Self {
        self.envs(vars)
    }

    fn env_remove(&mut self, key: impl AsRef<OsStr>) -> &mut Self {
        self.env_remove(key)
    }

    fn env_clear(&mut self) -> &mut Self {
        self.env_clear()
    }

    fn current_dir(&mut self, dir: impl AsRef<std::path::Path>) -> &mut Self {
        self.current_dir(dir)
    }

    fn stdin(&mut self, cfg: impl Into<Stdio>) -> &mut Self {
        self.stdin(cfg)
    }

    fn stdout(&mut self, cfg: impl Into<Stdio>) -> &mut Self {
        self.stdout(cfg)
    }

    fn stderr(&mut self, cfg: impl Into<Stdio>) -> &mut Self {
        self.stderr(cfg)
    }

    fn kill_on_drop(&mut self, kill_on_drop: bool) -> &mut Self {
        self.kill_on_drop(kill_on_drop)
    }

    fn spawn(&mut self) -> Result<Self::Child> {
        self.spawn()
    }

    fn status(&mut self) -> impl Future<Output = Result<ExitStatus>> {
        self.status()
    }

    fn output(&mut self) -> impl Future<Output = Result<Output>> {
        self.output()
    }
}

#[cfg(unix)]
impl CommandExt for tokio::process::Command {
    fn uid(&mut self, uid: u32) -> &mut Self {
        self.uid(uid)
    }

    fn gid(&mut self, gid: u32) -> &mut Self {
        self.gid(gid)
    }

    fn arg0(&mut self, arg0: impl AsRef<OsStr>) -> &mut Self {
        self.arg0(arg0)
    }
}

impl Child for tokio::process::Child {
    type Stdin = Compat<ChildStdin>;
    type StdinRef<'a> = Compat<&'a mut ChildStdin>;
    type Stdout = Compat<ChildStdout>;
    type StdoutRef<'a> = Compat<&'a mut ChildStdout>;
    type Stderr = Compat<ChildStderr>;
    type StderrRef<'a> = Compat<&'a mut ChildStderr>;

    fn stdin(&mut self) -> Option<Self::StdinRef<'_>> {
        self.stdin.as_mut().map(WriteCompat::compat_write)
    }

    fn take_stdin(&mut self) -> Option<Self::Stdin> {
        self.stdin.take().map(WriteCompat::compat_write)
    }

    fn stdout(&mut self) -> Option<Self::StdoutRef<'_>> {
        self.stdout.as_mut().map(ReadCompat::compat)
    }

    fn take_stdout(&mut self) -> Option<Self::Stdout> {
        self.stdout.take().map(ReadCompat::compat)
    }

    fn stderr(&mut self) -> Option<Self::StderrRef<'_>> {
        self.stderr.as_mut().map(ReadCompat::compat)
    }

    fn take_stderr(&mut self) -> Option<Self::Stderr> {
        self.stderr.take().map(ReadCompat::compat)
    }

    fn id(&self) -> Option<u32> {
        self.id()
    }

    fn kill(&mut self) -> Result<()> {
        self.start_kill()
    }

    fn try_status(&mut self) -> Result<Option<ExitStatus>> {
        self.try_wait()
    }

    fn status(&mut self) -> impl Future<Output = Result<ExitStatus>> {
        self.wait()
    }

    fn output(self) -> impl Future<Output = Result<Output>> {
        self.wait_with_output()
    }
}

impl AsyncStdio for Compat<ChildStdin> {
    async fn into_stdio(self) -> Result<Stdio> {
        self.into_inner().try_into()
    }
}

impl AsyncStdio for Compat<ChildStdout> {
    async fn into_stdio(self) -> Result<Stdio> {
        self.into_inner().try_into()
    }
}

impl AsyncStdio for Compat<ChildStderr> {
    async fn into_stdio(self) -> Result<Stdio> {
        self.into_inner().try_into()
    }
}