use crate::sys::io::{Io, IoRead, IoResult};
use crate::work::process::{Command, ExitStatus, Output, Stdio};
#[doc = crate::_tags!(platform runtime)]
#[doc = crate::_doc_location!("work/process")]
#[derive(Debug)]
pub struct CommandFlow {
cmds: Vec<Command>,
}
#[rustfmt::skip]
impl CommandFlow {
pub fn new(cmd: Command) -> Self { Self { cmds: vec![cmd] } }
pub fn then(mut self, mut next: Command) -> Self {
let (reader, writer) = Io::pipe().expect("pipe failed");
let left = self.cmds.last_mut().unwrap();
left.stdout(Stdio::from(writer));
next.stdin(Stdio::from(reader));
self.cmds.push(next);
self
}
pub fn run(self) -> IoResult<ExitStatus> {
let mut children = Vec::with_capacity(self.cmds.len());
for mut cmd in self.cmds { children.push(cmd.spawn()?); }
let mut last_status = None;
for mut child in children { last_status = Some(child.wait()?); }
Ok(last_status.unwrap())
}
pub fn stdout(mut self) -> IoResult<Output> {
let (mut reader, writer) = Io::pipe()?;
let last = self.cmds.last_mut().unwrap();
last.stdout(Stdio::from(writer));
let mut children = Vec::with_capacity(self.cmds.len());
for mut cmd in self.cmds { children.push(cmd.spawn()?); }
let mut output = Vec::new();
reader.read_to_end(&mut output)?;
let mut last_status = ExitStatus::default();
for mut child in children { last_status = child.wait()?; }
Ok(Output { status: last_status, stdout: output, stderr: Vec::new() })
}
pub fn output(mut self) -> IoResult<Output> {
let (mut reader, writer) = Io::pipe()?;
let last = self.cmds.last_mut().unwrap();
last.stdout(Stdio::from(writer.try_clone()?));
last.stderr(Stdio::from(writer));
let mut children = Vec::with_capacity(self.cmds.len());
for mut cmd in self.cmds { children.push(cmd.spawn()?); }
let mut output = Vec::new();
reader.read_to_end(&mut output)?;
let mut last_status = ExitStatus::default();
for mut child in children { last_status = child.wait()?; }
Ok(Output { status: last_status, stdout: output, stderr: Vec::new() })
}
pub fn stdout_with<F>(mut self, mut f: F) -> IoResult<ExitStatus> where F: FnMut(&[u8]) {
let (mut reader, writer) = Io::pipe()?;
let last = self.cmds.last_mut().unwrap();
last.stdout(Stdio::from(writer));
let mut children = Vec::with_capacity(self.cmds.len());
for mut cmd in self.cmds { children.push(cmd.spawn()?); }
let mut buf = [0u8; 8192];
loop {
let n = reader.read(&mut buf)?;
if n == 0 { break; }
f(&buf[..n]);
}
let mut last_status = None;
for mut child in children { last_status = Some(child.wait()?); }
Ok(last_status.unwrap())
}
}