1use serde::{Deserialize, Serialize};
6use std::fmt;
7use uuid::Uuid;
8
9use crate::error::CoreError;
10
11#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
13pub struct WorkflowId(String);
14
15impl WorkflowId {
16 pub fn new(id: impl Into<String>) -> Result<Self, CoreError> {
21 let id = id.into();
22 if id.is_empty() {
23 return Err(CoreError::InvalidId("WorkflowId cannot be empty".to_string()));
24 }
25 Ok(Self(id))
26 }
27
28 #[must_use]
30 pub fn generate() -> Self {
31 Self(Uuid::new_v4().to_string())
32 }
33
34 #[must_use]
36 pub fn as_str(&self) -> &str {
37 &self.0
38 }
39}
40
41impl fmt::Display for WorkflowId {
42 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
43 write!(f, "{}", self.0)
44 }
45}
46
47#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
49pub struct PlanId(String);
50
51impl PlanId {
52 pub fn new(id: impl Into<String>) -> Result<Self, CoreError> {
57 let id = id.into();
58 if id.is_empty() {
59 return Err(CoreError::InvalidId("PlanId cannot be empty".to_string()));
60 }
61 Ok(Self(id))
62 }
63
64 #[must_use]
66 pub fn generate() -> Self {
67 Self(Uuid::new_v4().to_string())
68 }
69
70 #[must_use]
72 pub fn as_str(&self) -> &str {
73 &self.0
74 }
75}
76
77impl fmt::Display for PlanId {
78 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
79 write!(f, "{}", self.0)
80 }
81}
82
83#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
85pub struct StepId(String);
86
87impl StepId {
88 pub fn new(id: impl Into<String>) -> Result<Self, CoreError> {
93 let id = id.into();
94 if id.is_empty() {
95 return Err(CoreError::InvalidId("StepId cannot be empty".to_string()));
96 }
97 Ok(Self(id))
98 }
99
100 #[must_use]
102 pub fn generate() -> Self {
103 Self(Uuid::new_v4().to_string())
104 }
105
106 #[must_use]
108 pub fn as_str(&self) -> &str {
109 &self.0
110 }
111}
112
113impl fmt::Display for StepId {
114 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
115 write!(f, "{}", self.0)
116 }
117}
118
119#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
121pub struct ExecutionId(String);
122
123impl ExecutionId {
124 pub fn new(id: impl Into<String>) -> Result<Self, CoreError> {
129 let id = id.into();
130 if id.is_empty() {
131 return Err(CoreError::InvalidId("ExecutionId cannot be empty".to_string()));
132 }
133 Ok(Self(id))
134 }
135
136 #[must_use]
138 pub fn generate() -> Self {
139 Self(Uuid::new_v4().to_string())
140 }
141
142 #[must_use]
144 pub fn as_str(&self) -> &str {
145 &self.0
146 }
147}
148
149impl fmt::Display for ExecutionId {
150 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
151 write!(f, "{}", self.0)
152 }
153}
154
155#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
157pub struct DecisionId(String);
158
159impl DecisionId {
160 pub fn new(id: impl Into<String>) -> Result<Self, CoreError> {
165 let id = id.into();
166 if id.is_empty() {
167 return Err(CoreError::InvalidId("DecisionId cannot be empty".to_string()));
168 }
169 Ok(Self(id))
170 }
171
172 #[must_use]
174 pub fn generate() -> Self {
175 Self(Uuid::new_v4().to_string())
176 }
177
178 #[must_use]
180 pub fn as_str(&self) -> &str {
181 &self.0
182 }
183}
184
185impl fmt::Display for DecisionId {
186 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
187 write!(f, "{}", self.0)
188 }
189}
190
191#[cfg(test)]
192mod tests {
193 use super::*;
194
195 #[test]
196 fn test_workflow_id_new() {
197 let id = WorkflowId::new("test-workflow").unwrap();
198 assert_eq!(id.as_str(), "test-workflow");
199 }
200
201 #[test]
202 fn test_workflow_id_empty() {
203 let result = WorkflowId::new("");
204 assert!(result.is_err());
205 }
206
207 #[test]
208 fn test_workflow_id_generate() {
209 let id1 = WorkflowId::generate();
210 let id2 = WorkflowId::generate();
211 assert_ne!(id1, id2);
212 }
213
214 #[test]
215 fn test_plan_id_new() {
216 let id = PlanId::new("test-plan").unwrap();
217 assert_eq!(id.as_str(), "test-plan");
218 }
219
220 #[test]
221 fn test_step_id_new() {
222 let id = StepId::new("test-step").unwrap();
223 assert_eq!(id.as_str(), "test-step");
224 }
225
226 #[test]
227 fn test_execution_id_new() {
228 let id = ExecutionId::new("test-execution").unwrap();
229 assert_eq!(id.as_str(), "test-execution");
230 }
231
232 #[test]
233 fn test_decision_id_new() {
234 let id = DecisionId::new("test-decision").unwrap();
235 assert_eq!(id.as_str(), "test-decision");
236 }
237}