std_ext/
command.rs

1pub trait CommandExt {
2    fn run(&mut self) -> std::io::Result<()>;
3    fn check_output(&mut self) -> std::io::Result<std::process::Output>;
4}
5
6pub trait OutputExt {
7    fn stdout(&self) -> &str;
8    fn stderr(&self) -> &str;
9    fn success(&self) -> bool;
10}
11
12impl CommandExt for std::process::Command {
13    fn run(&mut self) -> std::io::Result<()> {
14        let status = self.status()?;
15        if !status.success() {
16            return Err(std::io::Error::new(
17                std::io::ErrorKind::Other,
18                format!("Command exited with code: {}", status.code().unwrap()),
19            ));
20        }
21        Ok(())
22    }
23
24    fn check_output(&mut self) -> std::io::Result<std::process::Output> {
25        let output = self.output()?;
26        if output.status.success() {
27            Ok(output)
28        } else {
29            Err(std::io::Error::new(
30                std::io::ErrorKind::Other,
31                format!(
32                    "Command exited with code: {}",
33                    output.status.code().unwrap()
34                ),
35            ))
36        }
37    }
38}
39
40impl OutputExt for std::process::Output {
41    fn stdout(&self) -> &str {
42        std::str::from_utf8(&self.stdout).expect("Failed to convert stdout to str")
43    }
44
45    fn stderr(&self) -> &str {
46        std::str::from_utf8(&self.stderr).expect("Failed to convert stderr to str")
47    }
48    fn success(&self) -> bool {
49        self.status.success()
50    }
51}
52
53#[cfg(test)]
54mod tests {
55    use super::*;
56
57    #[test]
58    fn test_output() -> std::io::Result<()> {
59        let output = std::process::Command::new("echo").arg("hello").output()?;
60        let s = output.stdout();
61        assert_eq!(s, "hello\n");
62        Ok(())
63    }
64
65    #[test]
66    fn test_run() -> std::io::Result<()> {
67        std::process::Command::new("echo").arg("hello").run()?;
68        Ok(())
69    }
70}