io_process/coroutines/
spawn-then-wait.rs1use log::{debug, trace};
4use thiserror::Error;
5
6use crate::{command::Command, io::ProcessIo, status::SpawnStatus};
7
8#[derive(Debug, Error)]
10pub enum SpawnThenWaitError {
11 #[error("Invalid argument: expected {0}, got {1:?}")]
17 InvalidArgument(&'static str, ProcessIo),
18
19 #[error("Command not initialized")]
21 NotInitialized,
22}
23
24#[derive(Debug)]
26pub enum SpawnThenWaitResult {
27 Ok(SpawnStatus),
29
30 Io(ProcessIo),
32
33 Err(SpawnThenWaitError),
35}
36
37#[derive(Debug)]
47pub struct SpawnThenWait {
48 cmd: Option<Command>,
49}
50
51impl SpawnThenWait {
52 pub fn new(command: Command) -> Self {
54 trace!("prepare command to be spawned: {command:?}");
55 let cmd = Some(command);
56 Self { cmd }
57 }
58
59 pub fn resume(&mut self, arg: Option<ProcessIo>) -> SpawnThenWaitResult {
61 let Some(arg) = arg else {
62 let Some(cmd) = self.cmd.take() else {
63 return SpawnThenWaitResult::Err(SpawnThenWaitError::NotInitialized);
64 };
65
66 trace!("break: need I/O to spawn command");
67 return SpawnThenWaitResult::Io(ProcessIo::SpawnThenWait(Err(cmd)));
68 };
69
70 trace!("resume after spawning command");
71
72 let ProcessIo::SpawnThenWait(io) = arg else {
73 let err = SpawnThenWaitError::InvalidArgument("spawn output", arg);
74 return SpawnThenWaitResult::Err(err);
75 };
76
77 let output = match io {
78 Ok(output) => output,
79 Err(cmd) => return SpawnThenWaitResult::Io(ProcessIo::SpawnThenWait(Err(cmd))),
80 };
81
82 debug!("spawned command: {:?}", output.status);
83 SpawnThenWaitResult::Ok(output)
84 }
85}