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 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}