medic_lib/step_result/
mod.rs

1use std::io::{self, Write};
2use std::ops::{ControlFlow, FromResidual, Try};
3
4pub enum StepResult {
5    StepOk,
6    StepError(String, Option<String>, Option<String>),
7}
8
9impl std::process::Termination for StepResult {
10    fn report(self) -> std::process::ExitCode {
11        match self {
12            StepResult::StepOk => std::process::ExitCode::from(0),
13            StepResult::StepError(msg, stdout, stderr) => {
14                eprintln!("\x1b[31;1mError:\x1b[0m {msg}\r\n");
15                if let Some(stdout) = stdout {
16                    if !stdout.is_empty() {
17                        eprintln!("\x1b[31;1mstdout:\x1b[0m\r\n{stdout}");
18                    }
19                }
20                if let Some(stderr) = stderr {
21                    if !stderr.is_empty() {
22                        eprintln!("\x1b[31;1mstderr:\x1b[0m\r\n{stderr}");
23                    }
24                }
25                io::stderr().flush().unwrap();
26
27                std::process::ExitCode::from(1)
28            }
29        }
30    }
31}
32
33pub struct ResultCodeResidual(String, Option<String>, Option<String>);
34
35impl Try for StepResult {
36    type Output = ();
37    type Residual = ResultCodeResidual;
38
39    fn branch(self) -> ControlFlow<Self::Residual> {
40        match self {
41            StepResult::StepError(msg, stdout, stderr) => {
42                ControlFlow::Break(ResultCodeResidual(msg, stdout, stderr))
43            }
44            StepResult::StepOk => ControlFlow::Continue(()),
45        }
46    }
47    fn from_output((): ()) -> Self {
48        StepResult::StepOk
49    }
50}
51
52impl FromResidual for StepResult {
53    fn from_residual(r: ResultCodeResidual) -> Self {
54        Self::StepError(r.0, r.1, r.2)
55    }
56}