gq_core/query/
format.rs

1use std::{
2    fmt::{self, Display, Formatter},
3    io,
4};
5
6use thiserror::Error;
7
8use crate::format::Indentation;
9
10use super::{ChildQuery, Query};
11
12#[derive(Debug, Error)]
13pub enum Error {
14    #[error("IO error while formatting: {0}")]
15    Io(#[from] io::Error),
16}
17
18pub type Result<T> = std::result::Result<T, Error>;
19
20impl Query {
21    // TODO: do a test for this function, so parsing a formatted query, outputs the
22    // same original query...
23    pub fn pretty_format(&self, indentation: Indentation) -> String {
24        let mut result = String::new();
25
26        let arguments = self.arguments();
27        if !arguments.0.is_empty() {
28            result.push_str(&format!("({arguments})"));
29        }
30        let key = self.key();
31        if !key.keys().is_empty() {
32            if self.children().is_empty() {
33                result.push_str(&key.to_string());
34                return result;
35            }
36            result.push_str(&format!("{key} "));
37        } else if self.children().is_empty() {
38            result.push_str("{ }");
39            return result;
40        }
41
42        result.push_str(&format!("{{{}", indentation.level_separator()));
43        for child in self.children() {
44            child.do_pretty_format(&mut result, indentation, 1);
45        }
46        result.push('}');
47
48        result
49    }
50
51    pub fn pretty_format_to_writer<W: io::Write>(
52        &self,
53        writer: &mut W,
54        indentation: Indentation,
55    ) -> Result<()> {
56        let formatted = self.pretty_format(indentation);
57        Ok(writer.write_all(formatted.as_bytes())?)
58    }
59}
60
61impl ChildQuery {
62    fn do_pretty_format(&self, result: &mut String, indentation: Indentation, level: usize) {
63        let indent_string = indentation.at_level(level);
64        let sep = indentation.level_separator();
65
66        let query_key = self.key();
67
68        result.push_str(&format!("{indent_string}{query_key}"));
69        if let Some(alias) = self.alias() {
70            result.push_str(&format!(": {alias}"));
71        }
72
73        if !self.children().is_empty() {
74            result.push_str(&format!(" {{{sep}"));
75            for child in self.children() {
76                child.do_pretty_format(result, indentation, level + 1);
77            }
78            result.push_str(&format!("{indent_string}}}{sep}"));
79        } else {
80            result.push(sep);
81        }
82    }
83}
84
85impl Display for Query {
86    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
87        let formatted = self.pretty_format(Default::default());
88        formatted.fmt(f)
89    }
90}