Skip to main content

mant_engine/output/
json.rs

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