agentic_workflow/format/
writer.rs1use std::io::Write;
2
3use crate::types::{Workflow, WorkflowError, WorkflowResult};
4
5pub const AWF_MAGIC: &[u8; 4] = b"AWFL";
7pub const AWF_VERSION: u32 = 1;
9
10#[repr(u8)]
12#[derive(Debug, Clone, Copy)]
13pub enum SectionType {
14 WorkflowRegistry = 1,
15 TemplateLibrary = 2,
16 ExecutionHistory = 3,
17 ScheduleTable = 4,
18 StateMachineTable = 5,
19 TriggerIndex = 6,
20 AuditLog = 7,
21 IdempotencyCache = 8,
22 VariableStore = 9,
23}
24
25pub struct AwfWriter<W: Write> {
27 writer: W,
28 workflow_count: u32,
29 execution_count: u32,
30}
31
32impl<W: Write> AwfWriter<W> {
33 pub fn new(writer: W) -> Self {
34 Self {
35 writer,
36 workflow_count: 0,
37 execution_count: 0,
38 }
39 }
40
41 pub fn write_header(&mut self) -> WorkflowResult<()> {
43 self.writer.write_all(AWF_MAGIC)?;
45 self.writer.write_all(&AWF_VERSION.to_le_bytes())?;
47 self.writer.write_all(&0u32.to_le_bytes())?;
49 self.writer.write_all(&0u32.to_le_bytes())?;
51
52 Ok(())
53 }
54
55 pub fn write_section_header(
57 &mut self,
58 section_type: SectionType,
59 data_len: u32,
60 ) -> WorkflowResult<()> {
61 self.writer.write_all(&[section_type as u8])?;
62 self.writer.write_all(&data_len.to_le_bytes())?;
63 Ok(())
64 }
65
66 pub fn write_workflow(&mut self, workflow: &Workflow) -> WorkflowResult<()> {
68 let json = serde_json::to_vec(workflow)
69 .map_err(|e| WorkflowError::SerializationError(e.to_string()))?;
70
71 let checksum = blake3::hash(&json);
72
73 self.write_section_header(SectionType::WorkflowRegistry, json.len() as u32)?;
74 self.writer.write_all(&json)?;
75 self.writer.write_all(checksum.as_bytes())?;
76
77 self.workflow_count += 1;
78 Ok(())
79 }
80
81 pub fn write_json_section(
83 &mut self,
84 section_type: SectionType,
85 data: &serde_json::Value,
86 ) -> WorkflowResult<()> {
87 let json = serde_json::to_vec(data)
88 .map_err(|e| WorkflowError::SerializationError(e.to_string()))?;
89
90 let checksum = blake3::hash(&json);
91
92 self.write_section_header(section_type, json.len() as u32)?;
93 self.writer.write_all(&json)?;
94 self.writer.write_all(checksum.as_bytes())?;
95
96 Ok(())
97 }
98
99 pub fn finish(mut self) -> WorkflowResult<W> {
101 self.writer.flush()?;
102 Ok(self.writer)
103 }
104
105 pub fn workflow_count(&self) -> u32 {
107 self.workflow_count
108 }
109}
110
111#[cfg(test)]
112mod tests {
113 use super::*;
114
115 #[test]
116 fn test_write_header() {
117 let mut buf = Vec::new();
118 let mut writer = AwfWriter::new(&mut buf);
119 writer.write_header().unwrap();
120 assert_eq!(&buf[0..4], AWF_MAGIC);
121 }
122
123 #[test]
124 fn test_write_workflow() {
125 let mut buf = Vec::new();
126 {
127 let mut writer = AwfWriter::new(&mut buf);
128 writer.write_header().unwrap();
129
130 let wf = Workflow::new("test", "A test workflow");
131 writer.write_workflow(&wf).unwrap();
132 assert_eq!(writer.workflow_count(), 1);
133 writer.finish().unwrap();
134 }
135
136 assert!(buf.len() > 16);
137 }
138}