Skip to main content

made_core/value_objects/ceremony/
step_result.rs

1use serde::{Deserialize, Serialize};
2
3use crate::error::DomainError;
4
5use super::{StepErrorMessage, StepOutput, StepStatus};
6
7#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
8pub struct StepResult {
9    status: StepStatus,
10    output: StepOutput,
11    error_message: Option<StepErrorMessage>,
12}
13
14impl StepResult {
15    pub fn new(
16        status: StepStatus,
17        output: StepOutput,
18        error_message: Option<StepErrorMessage>,
19    ) -> Result<Self, DomainError> {
20        if matches!(status, StepStatus::Pending | StepStatus::InProgress) {
21            return Err(DomainError::InvariantViolated {
22                reason: "step result status must be observable",
23            });
24        }
25        if status == StepStatus::Failed && error_message.is_none() {
26            return Err(DomainError::EmptyField {
27                field: "step_result.error_message",
28            });
29        }
30        if status != StepStatus::Failed && error_message.is_some() {
31            return Err(DomainError::InvariantViolated {
32                reason: "only failed step results may carry an error message",
33            });
34        }
35        Ok(Self {
36            status,
37            output,
38            error_message,
39        })
40    }
41
42    pub fn completed(output: StepOutput) -> Result<Self, DomainError> {
43        Self::new(StepStatus::Completed, output, None)
44    }
45
46    pub fn waiting_for_human(output: StepOutput) -> Result<Self, DomainError> {
47        Self::new(StepStatus::WaitingForHuman, output, None)
48    }
49
50    pub fn failed(error_message: StepErrorMessage) -> Result<Self, DomainError> {
51        Self::new(StepStatus::Failed, StepOutput::empty(), Some(error_message))
52    }
53
54    #[must_use]
55    pub fn status(&self) -> StepStatus {
56        self.status
57    }
58
59    #[must_use]
60    pub fn output(&self) -> &StepOutput {
61        &self.output
62    }
63
64    #[must_use]
65    pub fn error_message(&self) -> Option<&StepErrorMessage> {
66        self.error_message.as_ref()
67    }
68
69    #[must_use]
70    pub fn into_parts(self) -> (StepStatus, StepOutput, Option<StepErrorMessage>) {
71        (self.status, self.output, self.error_message)
72    }
73
74    #[must_use]
75    pub fn is_success(&self) -> bool {
76        self.status.is_success()
77    }
78}