use std::process::Stdio;
use tokio::process::{Child as TokioChild, Command as TokioCommand};
use crate::{BoxedFuture, Context as _};
use super::{ChildInConfig, ChildOutConfig, ChildOutTask};
#[inline(always)]
pub fn pipe() -> Pipe {
Pipe
}
pub struct Pipe;
impl ChildOutConfig for Pipe {
type Task = PipeTask;
type __Null = super::__OCNonNull;
fn configure_stdout(&mut self, command: &mut TokioCommand) {
command.stdout(std::process::Stdio::piped());
}
fn configure_stderr(&mut self, command: &mut TokioCommand) {
command.stderr(std::process::Stdio::piped());
}
fn take(
self,
child: &mut TokioChild,
_name: Option<&str>,
is_out: bool,
) -> crate::Result<Self::Task> {
let stream = super::take_child_out(child, is_out)?;
let x: Result<Stdio, _> = match stream {
Ok(s) => s.try_into(),
Err(s) => s.try_into(),
};
let x = x.context("failed to convert tokio pipe to std pipe")?;
Ok(PipeTask(x))
}
}
pub struct PipeTask(Stdio);
impl ChildOutTask for PipeTask {
type Output = PipeOutput;
fn run(self) -> (Option<BoxedFuture<()>>, Self::Output) {
(None, PipeOutput(Some(self.0)))
}
}
pub struct PipeOutput(Option<Stdio>); impl ChildInConfig for PipeOutput {
type Task = ();
fn configure_stdin(&mut self, command: &mut TokioCommand) -> crate::Result<()> {
match self.0.take() {
Some(x) => {
command.stdin(x);
Ok(())
}
_ => crate::bail!("unexpected: pipe was already taken"),
}
}
fn take(self, _: &mut TokioChild) -> crate::Result<Self::Task> {
Ok(())
}
}