1use super::{QuantumDecoder, QuantumEntry, TraversalCode};
5use anyhow::Result;
6use serde_json::{json, Value};
7use std::io::Write;
8
9pub struct JsonDecoder {
10 stack: Vec<Value>,
11 current_children: Vec<Value>,
12}
13
14impl Default for JsonDecoder {
15 fn default() -> Self {
16 Self::new()
17 }
18}
19
20impl JsonDecoder {
21 pub fn new() -> Self {
22 Self {
23 stack: Vec::new(),
24 current_children: Vec::new(),
25 }
26 }
27}
28
29impl QuantumDecoder for JsonDecoder {
30 fn init(&mut self, writer: &mut dyn Write) -> Result<()> {
31 writeln!(writer, "{{")?;
32 writeln!(writer, " \"format\": \"quantum-decoded\",")?;
33 writeln!(writer, " \"version\": \"1.0\",")?;
34 writeln!(writer, " \"tree\": [")?;
35 Ok(())
36 }
37
38 fn decode_entry(&mut self, entry: &QuantumEntry, _writer: &mut dyn Write) -> Result<()> {
39 let mut node = json!({
40 "name": entry.name,
41 "type": if entry.is_dir { "directory" } else { "file" },
42 });
43
44 if let Some(size) = entry.size {
45 node["size"] = json!(size);
46 }
47
48 if let Some(perms) = entry.perms_delta {
49 node["permissions_delta"] = json!(format!("0x{:04x}", perms));
50 }
51
52 match entry.traversal {
53 TraversalCode::Deeper => {
54 node["children"] = json!([]);
56 self.stack.push(node);
57 }
58 TraversalCode::Back => {
59 if let Some(mut parent) = self.stack.pop() {
61 parent["children"] = json!(self.current_children.clone());
62 self.current_children.clear();
63 self.current_children.push(parent);
64 }
65 }
66 TraversalCode::Same => {
67 self.current_children.push(node);
69 }
70 TraversalCode::Summary => {
71 self.current_children.push(node);
73 }
74 }
75
76 Ok(())
77 }
78
79 fn finish(&mut self, writer: &mut dyn Write) -> Result<()> {
80 while let Some(mut parent) = self.stack.pop() {
82 parent["children"] = json!(self.current_children.clone());
83 self.current_children.clear();
84 self.current_children.push(parent);
85 }
86
87 let tree_json = serde_json::to_string_pretty(&self.current_children)?;
89 write!(writer, "{}", tree_json)?;
90
91 writeln!(writer, "\n ]")?;
92 writeln!(writer, "}}")?;
93 Ok(())
94 }
95}