Skip to main content

mant_core/output/
json.rs

1//! Serializes stable native contracts directly from their Rust source types.
2
3use mant_ast::{QueryBundle, QueryExcerpt, QueryOutline, QuerySearch, TldrCacheUpdate};
4
5/// Serialize a query contract in compact or human-readable form.
6///
7/// # Errors
8///
9/// Propagates the unlikely JSON writer failure from [`serde_json`].
10pub fn render_query_json(query: &QueryBundle, pretty: bool) -> Result<String, serde_json::Error> {
11    render_json(query, pretty)
12}
13
14/// Serialize a complete query outline in compact or human-readable form.
15///
16/// # Errors
17///
18/// Propagates the unlikely JSON writer failure from [`serde_json`].
19pub fn render_outline_json(
20    outline: &QueryOutline,
21    pretty: bool,
22) -> Result<String, serde_json::Error> {
23    render_json(outline, pretty)
24}
25
26/// Serialize selected query nodes in compact or human-readable form.
27///
28/// # Errors
29///
30/// Propagates the unlikely JSON writer failure from [`serde_json`].
31pub fn render_excerpt_json(
32    excerpt: &QueryExcerpt,
33    pretty: bool,
34) -> Result<String, serde_json::Error> {
35    render_json(excerpt, pretty)
36}
37
38/// Serialize structure-aware search results in compact or human-readable form.
39///
40/// # Errors
41///
42/// Propagates the unlikely JSON writer failure from [`serde_json`].
43pub fn render_search_json(search: &QuerySearch, pretty: bool) -> Result<String, serde_json::Error> {
44    render_json(search, pretty)
45}
46
47/// Serialize the explicit tldr update result for a process boundary.
48///
49/// # Errors
50///
51/// Propagates the unlikely JSON writer failure from [`serde_json`].
52pub fn render_update_json(
53    update: &TldrCacheUpdate,
54    pretty: bool,
55) -> Result<String, serde_json::Error> {
56    render_json(update, pretty)
57}
58
59fn render_json(value: &impl serde::Serialize, pretty: bool) -> Result<String, serde_json::Error> {
60    if pretty {
61        serde_json::to_string_pretty(value)
62    } else {
63        serde_json::to_string(value)
64    }
65}
66
67#[cfg(test)]
68mod tests {
69    use mant_ast::{QueryBundle, QuerySchema, TldrCacheAction, TldrCacheUpdate};
70
71    use super::{render_query_json, render_update_json};
72
73    #[test]
74    fn compact_and_pretty_query_output_share_the_same_contract() {
75        let query = QueryBundle {
76            schema: QuerySchema::V6,
77            label: "ls".to_owned(),
78            document: None,
79            tldr: None,
80        };
81        let compact = render_query_json(&query, false).expect("compact JSON");
82        let pretty = render_query_json(&query, true).expect("pretty JSON");
83
84        assert_eq!(compact, r#"{"schema":"mant.query/v6","label":"ls"}"#);
85        assert!(pretty.contains("\n  \"label\": \"ls\""));
86        assert_eq!(
87            serde_json::from_str::<serde_json::Value>(&compact).expect("compact value"),
88            serde_json::from_str::<serde_json::Value>(&pretty).expect("pretty value")
89        );
90    }
91
92    #[test]
93    fn update_json_omits_absent_provider_fields() {
94        let update = TldrCacheUpdate {
95            action: TldrCacheAction::Cloned,
96            cache_dir: Some("/cache/tldr".to_owned()),
97            client: None,
98            output: None,
99            revision: Some("abc123".to_owned()),
100        };
101
102        assert_eq!(
103            render_update_json(&update, false).expect("update JSON"),
104            r#"{"action":"cloned","cacheDir":"/cache/tldr","revision":"abc123"}"#
105        );
106        assert!(
107            render_update_json(&update, true)
108                .expect("pretty update JSON")
109                .contains("\n  \"cacheDir\": \"/cache/tldr\",")
110        );
111    }
112}