context_creator/formatters/
xml.rs

1//! XML formatter for context generation
2
3use super::{DigestData, DigestFormatter};
4use crate::core::walker::FileInfo;
5use anyhow::Result;
6
7/// Formatter that outputs XML format
8pub struct XmlFormatter {
9    buffer: String,
10    in_files_section: bool,
11}
12
13impl XmlFormatter {
14    /// Create a new XmlFormatter
15    pub fn new() -> Self {
16        Self {
17            buffer: String::from("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<context_creator>\n"),
18            in_files_section: false,
19        }
20    }
21}
22
23impl Default for XmlFormatter {
24    fn default() -> Self {
25        Self::new()
26    }
27}
28
29impl DigestFormatter for XmlFormatter {
30    fn render_header(&mut self, _data: &DigestData) -> Result<()> {
31        // XML doesn't need a separate header
32        Ok(())
33    }
34
35    fn render_statistics(&mut self, data: &DigestData) -> Result<()> {
36        self.buffer.push_str("  <file_summary>\n");
37        self.buffer.push_str(&format!(
38            "    <total_files>{}</total_files>\n",
39            data.files.len()
40        ));
41        self.buffer.push_str("  </file_summary>\n");
42        Ok(())
43    }
44
45    fn render_file_tree(&mut self, _data: &DigestData) -> Result<()> {
46        // File tree not needed for basic XML format
47        Ok(())
48    }
49
50    fn render_toc(&mut self, _data: &DigestData) -> Result<()> {
51        // Table of contents not needed for basic XML format
52        Ok(())
53    }
54
55    fn render_file_details(&mut self, file: &FileInfo, data: &DigestData) -> Result<()> {
56        // Start files section if not started
57        if !self.in_files_section {
58            self.buffer.push_str("  <files>\n");
59            self.in_files_section = true;
60        }
61
62        // Read file content
63        if let Ok(content) = data.cache.get_or_load(&file.path) {
64            self.buffer.push_str(&format!(
65                "    <file path=\"{}\">\n",
66                file.relative_path.display()
67            ));
68            self.buffer.push_str("      <![CDATA[");
69            self.buffer.push_str(&content);
70            self.buffer.push_str("]]>\n");
71            self.buffer.push_str("    </file>\n");
72        }
73        Ok(())
74    }
75
76    fn finalize(mut self: Box<Self>) -> String {
77        // Close files section if it was opened
78        if self.in_files_section {
79            self.buffer.push_str("  </files>\n");
80        }
81        self.buffer.push_str("</context_creator>\n");
82        self.buffer
83    }
84
85    fn format_name(&self) -> &'static str {
86        "xml"
87    }
88}