indexbus_inspect/internal/
json.rs1use crate::internal::inspect::{Report, WakeInfo};
2
3fn escape_json_str(s: &str) -> String {
4 let mut out = String::with_capacity(s.len() + 8);
5 for ch in s.chars() {
6 match ch {
7 '"' => out.push_str("\\\""),
8 '\\' => out.push_str("\\\\"),
9 '\n' => out.push_str("\\n"),
10 '\r' => out.push_str("\\r"),
11 '\t' => out.push_str("\\t"),
12 c if c.is_control() => {
13 use core::fmt::Write;
14 let _ = write!(out, "\\u{:04x}", c as u32);
15 }
16 c => out.push(c),
17 }
18 }
19 out
20}
21
22fn write_kv_str(out: &mut String, k: &str, v: &str) {
23 out.push('"');
24 out.push_str(k);
25 out.push_str("\":\"");
26 out.push_str(&escape_json_str(v));
27 out.push('"');
28}
29
30fn write_kv_u64(out: &mut String, k: &str, v: u64) {
31 use core::fmt::Write;
32 out.push('"');
33 out.push_str(k);
34 out.push_str("\":");
35 let _ = write!(out, "{v}");
36}
37
38fn write_kv_u32(out: &mut String, k: &str, v: u32) {
39 write_kv_u64(out, k, v as u64);
40}
41
42fn write_wake(out: &mut String, wake: &WakeInfo) {
43 out.push_str("\"wake\":{");
44 write_kv_u64(out, "offset", wake.offset as u64);
45 out.push(',');
46 write_kv_u64(out, "size", wake.size as u64);
47 out.push(',');
48 out.push_str("\"present\":");
49 out.push_str(if wake.present { "true" } else { "false" });
50 out.push('}');
51}
52
53pub(crate) fn to_json(report: &Report) -> String {
54 let mut out = String::with_capacity(512);
55 out.push('{');
56
57 write_kv_str(&mut out, "path", &report.path);
58 out.push(',');
59
60 write_kv_str(&mut out, "kind", report.kind);
61 out.push(',');
62
63 write_kv_u32(&mut out, "magic", report.header_magic);
64 out.push(',');
65 write_kv_u32(&mut out, "version", report.header_version as u32);
66 out.push(',');
67 write_kv_u32(&mut out, "flags", report.header_flags as u32);
68 out.push(',');
69 write_kv_u32(&mut out, "capabilities", report.capabilities);
70 out.push(',');
71 write_kv_u32(&mut out, "layout_bytes", report.layout_bytes);
72 out.push(',');
73 write_kv_u64(&mut out, "mapped_bytes", report.mapped_bytes as u64);
74 out.push(',');
75 write_kv_u64(&mut out, "base_size", report.base_size as u64);
76 out.push(',');
77
78 out.push_str("\"cap_names\":[");
79 for (i, n) in report.cap_names.iter().enumerate() {
80 if i != 0 {
81 out.push(',');
82 }
83 out.push('"');
84 out.push_str(n);
85 out.push('"');
86 }
87 out.push_str("],");
88
89 match report.initialized {
90 Some(v) => {
91 write_kv_u32(&mut out, "initialized", v);
92 out.push(',');
93 }
94 None => {
95 out.push_str("\"initialized\":null,");
96 }
97 }
98
99 if let Some(wake) = &report.wake {
100 write_wake(&mut out, wake);
101 out.push(',');
102 } else {
103 out.push_str("\"wake\":null,");
104 }
105
106 out.push_str("\"offsets\":[");
107 for (i, (name, off)) in report.offsets.iter().enumerate() {
108 if i != 0 {
109 out.push(',');
110 }
111 out.push('{');
112 write_kv_str(&mut out, "name", name);
113 out.push(',');
114 write_kv_u64(&mut out, "offset", *off as u64);
115 out.push('}');
116 }
117 out.push(']');
118
119 out.push_str(",\"values\":[");
120 for (i, (name, val)) in report.values.iter().enumerate() {
121 if i != 0 {
122 out.push(',');
123 }
124 out.push('{');
125 write_kv_str(&mut out, "name", name);
126 out.push(',');
127 write_kv_str(&mut out, "value", val);
128 out.push('}');
129 }
130 out.push(']');
131
132 out.push('}');
133 out
134}