use std::{fmt::Display, path::Path, process::Stdio};
use regex::Regex;
use crate::{expr::short_circuit::ShortCircuit, util::Done};
use super::Predicate;
#[derive(Debug)]
pub enum ProcessPredicate {
Process { cmd: String, expected_stdout: Regex },
}
impl PartialEq for ProcessPredicate {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(
Self::Process {
cmd: l_cmd,
expected_stdout: l_expected_stdout,
},
Self::Process {
cmd: r_cmd,
expected_stdout: r_expected_stdout,
},
) => l_cmd == r_cmd && l_expected_stdout.as_str() == r_expected_stdout.as_str(),
}
}
}
impl Eq for ProcessPredicate {}
impl Display for ProcessPredicate {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ProcessPredicate::Process {
cmd,
expected_stdout: expected,
} => {
write!(f, "process(cmd={}, expected={})", cmd, expected.as_str())
}
}
}
}
impl<A, B, C> Predicate<A, B, C, ProcessPredicate> {
pub async fn eval_async_predicate(
self,
file_path: &Path,
) -> std::io::Result<ShortCircuit<Predicate<A, B, C, Done>>> {
match self {
Predicate::Process(x) => match x.as_ref() {
ProcessPredicate::Process {
cmd,
expected_stdout: expected,
} => {
use tokio::process::*;
let mut child = Command::new(cmd)
.arg(file_path)
.stdin(Stdio::null())
.stderr(Stdio::piped())
.stdout(Stdio::piped())
.spawn()?;
let processid = child.id();
let status = child.wait_with_output().await?;
let stdout = status.stdout;
let res = match String::from_utf8(stdout) {
Ok(utf8) => {
expected.is_match(&utf8)
}
Err(_) => todo!(), };
Ok(ShortCircuit::Known(res))
}
},
Predicate::Content(x) => Ok(ShortCircuit::Unknown(Predicate::Content(x))),
Predicate::Name(x) => Ok(ShortCircuit::Unknown(Predicate::Name(x))),
Predicate::Metadata(x) => Ok(ShortCircuit::Unknown(Predicate::Metadata(x))),
}
}
}