layout_audit/output/
json.rs

1use crate::types::StructLayout;
2use serde::Serialize;
3
4#[derive(Serialize)]
5struct Output<'a> {
6    version: &'static str,
7    structs: &'a [StructLayout],
8}
9
10pub struct JsonFormatter {
11    pretty: bool,
12}
13
14impl JsonFormatter {
15    pub fn new(pretty: bool) -> Self {
16        Self { pretty }
17    }
18
19    pub fn format(&self, layouts: &[StructLayout]) -> String {
20        let output = Output { version: env!("CARGO_PKG_VERSION"), structs: layouts };
21
22        if self.pretty {
23            serde_json::to_string_pretty(&output)
24                .unwrap_or_else(|e| format!("{{\"error\": \"{}\"}}", e))
25        } else {
26            serde_json::to_string(&output).unwrap_or_else(|e| format!("{{\"error\": \"{}\"}}", e))
27        }
28    }
29}
30
31#[cfg(test)]
32mod tests {
33    use super::*;
34    use crate::types::{LayoutMetrics, StructLayout};
35
36    fn layout(name: &str) -> StructLayout {
37        let mut s = StructLayout::new(name.to_string(), 8, Some(8));
38        s.metrics = LayoutMetrics { padding_bytes: 0, total_size: 8, ..LayoutMetrics::default() };
39        s
40    }
41
42    #[test]
43    fn json_formatter_pretty() {
44        let formatter = JsonFormatter::new(true);
45        let out = formatter.format(&[layout("Foo")]);
46        let parsed: serde_json::Value = serde_json::from_str(&out).expect("valid JSON");
47        assert!(parsed["structs"].is_array());
48    }
49
50    #[test]
51    fn json_formatter_compact() {
52        let formatter = JsonFormatter::new(false);
53        let out = formatter.format(&[layout("Foo")]);
54        assert!(out.contains("\"structs\""));
55    }
56}