allow_report/
allow_entry_json.rs1use crate::json::{json_string_array, option_json, option_u32_json};
2use allow_core::{AllowEntry, LastSeen, Lifecycle, Selector, json_escape, normalize_path};
3
4pub fn render_allow_entry_json(entry: &AllowEntry, indent: &str) -> String {
5 let path = entry.path.as_ref().map(normalize_path);
6 let mut out = String::new();
7 out.push_str("{\n");
8 out.push_str(&format!(
9 "{indent} \"id\": \"{}\",\n",
10 json_escape(&entry.id)
11 ));
12 out.push_str(&format!("{indent} \"kind\": \"{}\",\n", entry.kind));
13 out.push_str(&format!(
14 "{indent} \"family\": {},\n",
15 option_json(entry.family.as_deref())
16 ));
17 out.push_str(&format!(
18 "{indent} \"scope\": \"{}\",\n",
19 json_escape(&entry.path_or_glob())
20 ));
21 out.push_str(&format!(
22 "{indent} \"path\": {},\n",
23 option_json(path.as_deref())
24 ));
25 out.push_str(&format!(
26 "{indent} \"glob\": {},\n",
27 option_json(entry.glob.as_deref())
28 ));
29 out.push_str(&format!(
30 "{indent} \"owner\": \"{}\",\n",
31 json_escape(&entry.owner)
32 ));
33 out.push_str(&format!(
34 "{indent} \"classification\": \"{}\",\n",
35 json_escape(&entry.classification)
36 ));
37 out.push_str(&format!(
38 "{indent} \"reason\": \"{}\",\n",
39 json_escape(&entry.reason)
40 ));
41 out.push_str(&format!(
42 "{indent} \"evidence\": {},\n",
43 json_string_array(&entry.evidence)
44 ));
45 out.push_str(&format!(
46 "{indent} \"links\": {},\n",
47 json_string_array(&entry.links)
48 ));
49 out.push_str(&format!(
50 "{indent} \"occurrence_limit\": {},\n",
51 option_u32_json(entry.occurrence_limit)
52 ));
53 out.push_str(&format!(
54 "{indent} \"lifecycle\": {},\n",
55 lifecycle_json(&entry.lifecycle, indent)
56 ));
57 out.push_str(&format!(
58 "{indent} \"selector\": {},\n",
59 render_selector_json(&entry.selector, indent)
60 ));
61 out.push_str(&format!(
62 "{indent} \"last_seen\": {}\n",
63 render_last_seen_json(entry.last_seen.as_ref(), indent)
64 ));
65 out.push_str(&format!("{indent}}}"));
66 out
67}
68
69fn lifecycle_json(lifecycle: &Lifecycle, indent: &str) -> String {
70 format!(
71 "{{\n{indent} \"created\": {},\n{indent} \"review_after\": {},\n{indent} \"expires\": {}\n{indent} }}",
72 option_json(lifecycle.created.as_deref()),
73 option_json(lifecycle.review_after.as_deref()),
74 option_json(lifecycle.expires.as_deref())
75 )
76}
77
78pub fn render_selector_json(selector: &Selector, indent: &str) -> String {
79 format!(
80 "{{\n{indent} \"ast_kind\": {},\n{indent} \"container\": {},\n{indent} \"callee\": {},\n{indent} \"macro_name\": {},\n{indent} \"lint\": {},\n{indent} \"symbol\": {},\n{indent} \"receiver_fingerprint\": {},\n{indent} \"target_fingerprint\": {},\n{indent} \"normalized_snippet_hash\": {},\n{indent} \"line_hint\": {},\n{indent} \"glob\": {}\n{indent} }}",
81 option_json(selector.ast_kind.as_deref()),
82 option_json(selector.container.as_deref()),
83 option_json(selector.callee.as_deref()),
84 option_json(selector.macro_name.as_deref()),
85 option_json(selector.lint.as_deref()),
86 option_json(selector.symbol.as_deref()),
87 option_json(selector.receiver_fingerprint.as_deref()),
88 option_json(selector.target_fingerprint.as_deref()),
89 option_json(selector.normalized_snippet_hash.as_deref()),
90 option_u32_json(selector.line_hint),
91 option_json(selector.glob.as_deref())
92 )
93}
94
95pub fn render_last_seen_json(last_seen: Option<&LastSeen>, indent: &str) -> String {
96 last_seen
97 .map(|last_seen| {
98 format!(
99 "{{\n{indent} \"line\": {},\n{indent} \"column\": {}\n{indent} }}",
100 last_seen.line, last_seen.column
101 )
102 })
103 .unwrap_or_else(|| "null".to_string())
104}