io_process/coroutines/
spawn-then-wait-with-output.rs1use log::{debug, trace};
4use std::process::Output;
5use thiserror::Error;
6
7use crate::{command::Command, io::ProcessIo};
8
9#[derive(Debug, Error)]
11pub enum SpawnThenWaitWithOutputError {
12 #[error("Invalid argument: expected {0}, got {1:?}")]
18 InvalidArgument(&'static str, ProcessIo),
19
20 #[error("Command not initialized")]
22 NotInitialized,
23}
24
25#[derive(Debug)]
27pub enum SpawnThenWaitWithOutputResult {
28 Ok(Output),
30
31 Io(ProcessIo),
33
34 Err(SpawnThenWaitWithOutputError),
36}
37
38#[derive(Debug)]
48pub struct SpawnThenWaitWithOutput {
49 cmd: Option<Command>,
50}
51
52impl SpawnThenWaitWithOutput {
53 pub fn new(cmd: Command) -> Self {
55 trace!("prepare command to be spawned: {cmd:?}");
56 let cmd = Some(cmd);
57 Self { cmd }
58 }
59
60 pub fn resume(&mut self, arg: Option<ProcessIo>) -> SpawnThenWaitWithOutputResult {
62 let Some(arg) = arg else {
63 let Some(cmd) = self.cmd.take() else {
64 return SpawnThenWaitWithOutputResult::Err(
65 SpawnThenWaitWithOutputError::NotInitialized,
66 );
67 };
68
69 trace!("break: need I/O to spawn command");
70 return SpawnThenWaitWithOutputResult::Io(ProcessIo::SpawnThenWaitWithOutput(Err(cmd)));
71 };
72
73 trace!("resume after spawning command");
74
75 let ProcessIo::SpawnThenWaitWithOutput(io) = arg else {
76 let err = SpawnThenWaitWithOutputError::InvalidArgument("spawn output", arg);
77 return SpawnThenWaitWithOutputResult::Err(err);
78 };
79
80 let output = match io {
81 Ok(output) => output,
82 Err(cmd) => {
83 let io = ProcessIo::SpawnThenWaitWithOutput(Err(cmd));
84 return SpawnThenWaitWithOutputResult::Io(io);
85 }
86 };
87
88 debug!("spawned command: {:?}", output.status);
89 SpawnThenWaitWithOutputResult::Ok(output)
90 }
91}