Skip to main content

matrixcode_core/workflow/
parser.rs

1//! YAML Parser for Workflow Definitions
2//!
3//! 解析 YAML 格式的工作流定义文件。
4
5use anyhow::{Context, Result};
6use std::path::Path;
7
8use super::def::WorkflowDef;
9
10/// 从字符串解析工作流定义
11pub fn parse_workflow(yaml: &str) -> Result<WorkflowDef> {
12    let workflow: WorkflowDef = serde_yaml::from_str(yaml)
13        .with_context(|| "Failed to parse workflow YAML")?;
14
15    workflow.validate()
16        .with_context(|| "Workflow validation failed")?;
17
18    Ok(workflow)
19}
20
21/// 从文件解析工作流定义
22pub fn parse_workflow_from_file<P: AsRef<Path>>(path: P) -> Result<WorkflowDef> {
23    let content = std::fs::read_to_string(path.as_ref())
24        .with_context(|| "Failed to read workflow file")?;
25
26    parse_workflow(&content)
27}
28
29/// 将工作流定义序列化为 YAML
30pub fn to_yaml(workflow: &WorkflowDef) -> Result<String> {
31    serde_yaml::to_string(workflow)
32        .with_context(|| "Failed to serialize workflow to YAML")
33}
34
35#[cfg(test)]
36mod tests {
37    use super::*;
38
39    #[test]
40    fn test_parse_simple_workflow() {
41        let yaml = r#"
42id: test-workflow
43name: Test Workflow
44version: "1.0.0"
45nodes:
46  - id: start
47    type: start
48    name: Start
49  - id: end
50    type: end
51    name: End
52edges:
53  - from: start
54    to: end
55"#;
56        let workflow = parse_workflow(yaml);
57        assert!(workflow.is_ok());
58        let workflow = workflow.unwrap();
59        assert_eq!(workflow.id, "test-workflow");
60        assert_eq!(workflow.nodes.len(), 2);
61    }
62
63    #[test]
64    fn test_parse_workflow_with_task() {
65        let yaml = r#"
66id: task-workflow
67name: Task Workflow
68nodes:
69  - id: start
70    type: start
71    name: Start
72  - id: task1
73    type: task
74    name: Do Something
75    task: do_something
76    params:
77      arg1: value1
78    on_failure:
79      type: retry
80      max_attempts: 3
81      interval_ms: 1000
82  - id: end
83    type: end
84    name: End
85edges:
86  - from: start
87    to: task1
88  - from: task1
89    to: end
90"#;
91        let workflow = parse_workflow(yaml);
92        assert!(workflow.is_ok());
93    }
94
95    #[test]
96    fn test_parse_workflow_missing_start() {
97        let yaml = r#"
98id: invalid-workflow
99name: Invalid Workflow
100nodes:
101  - id: end
102    type: end
103    name: End
104"#;
105        let result = parse_workflow(yaml);
106        assert!(result.is_err());
107    }
108}