1use super::{CatOutput, FileOutput, TreeOutput};
2use quick_xml::events::{BytesCData, BytesDecl, BytesEnd, BytesStart, BytesText, Event};
3use quick_xml::Writer;
4use std::error::Error;
5use std::io::Cursor;
6
7pub fn output_tree(data: &TreeOutput) -> Result<(), Box<dyn Error>> {
8 let mut writer = Writer::new_with_indent(Cursor::new(Vec::new()), b' ', 2);
9
10 writer.write_event(Event::Decl(BytesDecl::new("1.0", Some("UTF-8"), None)))?;
11
12 let codebase = BytesStart::new("codebase");
13 writer.write_event(Event::Start(codebase.borrow()))?;
14
15 write_element(&mut writer, "project", &data.project)?;
16
17 let files = BytesStart::new("files");
18 writer.write_event(Event::Start(files.borrow()))?;
19
20 for file in &data.files {
21 write_file_element(&mut writer, file)?;
22 }
23
24 writer.write_event(Event::End(BytesEnd::new("files")))?;
25 writer.write_event(Event::End(BytesEnd::new("codebase")))?;
26
27 let result = writer.into_inner().into_inner();
28 println!("{}", String::from_utf8(result)?);
29 Ok(())
30}
31
32pub fn output_cat(data: &CatOutput) -> Result<(), Box<dyn Error>> {
33 let mut writer = Writer::new_with_indent(Cursor::new(Vec::new()), b' ', 2);
34
35 writer.write_event(Event::Decl(BytesDecl::new("1.0", Some("UTF-8"), None)))?;
36
37 let codebase = BytesStart::new("codebase");
38 writer.write_event(Event::Start(codebase.borrow()))?;
39
40 write_element(&mut writer, "project", &data.project)?;
41
42 if let Some(ref session) = data.session {
43 write_element(&mut writer, "session", session)?;
44 }
45
46 write_element(&mut writer, "files_shown", &data.files_shown.to_string())?;
47 write_element(
48 &mut writer,
49 "skipped_binary",
50 &data.skipped_binary.to_string(),
51 )?;
52 write_element(
53 &mut writer,
54 "skipped_session",
55 &data.skipped_session.to_string(),
56 )?;
57 write_element(&mut writer, "total_lines", &data.total_lines.to_string())?;
58
59 let files = BytesStart::new("files");
60 writer.write_event(Event::Start(files.borrow()))?;
61
62 for file in &data.files {
63 write_file_element(&mut writer, file)?;
64 }
65
66 writer.write_event(Event::End(BytesEnd::new("files")))?;
67 writer.write_event(Event::End(BytesEnd::new("codebase")))?;
68
69 let result = writer.into_inner().into_inner();
70 println!("{}", String::from_utf8(result)?);
71 Ok(())
72}
73
74fn write_file_element<W: std::io::Write>(
75 writer: &mut Writer<W>,
76 file: &FileOutput,
77) -> Result<(), Box<dyn Error>> {
78 let mut elem = BytesStart::new("file");
79 elem.push_attribute(("path", file.path.as_str()));
80 elem.push_attribute(("score", file.score.to_string().as_str()));
81 elem.push_attribute(("lines", file.lines.to_string().as_str()));
82
83 if let Some(tokens) = file.tokens {
84 elem.push_attribute(("tokens", tokens.to_string().as_str()));
85 }
86
87 if let Some(ref content) = file.content {
88 writer.write_event(Event::Start(elem.borrow()))?;
89
90 let content_elem = BytesStart::new("content");
91 writer.write_event(Event::Start(content_elem.borrow()))?;
92 writer.write_event(Event::CData(BytesCData::new(content)))?;
93 writer.write_event(Event::End(BytesEnd::new("content")))?;
94
95 writer.write_event(Event::End(BytesEnd::new("file")))?;
96 } else {
97 writer.write_event(Event::Empty(elem))?;
98 }
99
100 Ok(())
101}
102
103fn write_element<W: std::io::Write>(
104 writer: &mut Writer<W>,
105 name: &str,
106 content: &str,
107) -> Result<(), Box<dyn Error>> {
108 let elem = BytesStart::new(name);
109 writer.write_event(Event::Start(elem.borrow()))?;
110 writer.write_event(Event::Text(BytesText::new(content)))?;
111 writer.write_event(Event::End(BytesEnd::new(name)))?;
112 Ok(())
113}