fuel_indexer_graphql_parser/
format.rs1use std::default::Default;
3
4use crate::common::Directive;
5
6#[derive(Debug, PartialEq)]
7pub(crate) struct Formatter<'a> {
8 buf: String,
9 style: &'a Style,
10 indent: u32,
11}
12
13#[derive(Debug, PartialEq, Clone)]
18pub struct Style {
19 indent: u32,
20 multiline_arguments: bool,
21}
22
23impl Default for Style {
24 fn default() -> Style {
25 Style {
26 indent: 2,
27 multiline_arguments: false,
28 }
29 }
30}
31
32impl Style {
33 pub fn indent(&mut self, indent: u32) -> &mut Self {
35 self.indent = indent;
36 self
37 }
38
39 pub fn multiline_arguments(&mut self, multiline_arguments: bool) -> &mut Self {
41 self.multiline_arguments = multiline_arguments;
42 self
43 }
44}
45
46pub(crate) trait Displayable {
47 fn display(&self, f: &mut Formatter);
48}
49
50impl<'a> Formatter<'a> {
51 pub fn new(style: &Style) -> Formatter {
52 Formatter {
53 buf: String::with_capacity(1024),
54 style,
55 indent: 0,
56 }
57 }
58
59 pub fn indent(&mut self) {
60 for _ in 0..self.indent {
61 self.buf.push(' ');
62 }
63 }
64
65 pub fn endline(&mut self) {
66 self.buf.push('\n');
67 }
68
69 pub fn start_argument_block(&mut self, open_char: char) {
70 self.buf.push(open_char);
71 if self.style.multiline_arguments {
72 self.inc_indent();
73 }
74 }
75
76 pub fn end_argument_block(&mut self, close_char: char) {
77 if self.style.multiline_arguments {
78 self.endline();
79 self.dec_indent();
80 self.indent();
81 }
82 self.buf.push(close_char);
83 }
84
85 pub fn start_argument(&mut self) {
86 if self.style.multiline_arguments {
87 self.endline();
88 self.indent();
89 }
90 }
91
92 pub fn deliniate_argument(&mut self) {
93 self.buf.push(',');
94 if !self.style.multiline_arguments {
95 self.buf.push(' ');
96 }
97 }
98
99 pub fn start_block(&mut self) {
100 self.buf.push('{');
101 self.endline();
102 self.inc_indent();
103 }
104
105 pub fn end_block(&mut self) {
106 self.dec_indent();
107 self.indent();
108 self.buf.push('}');
109 self.endline();
110 }
111
112 pub fn margin(&mut self) {
113 if !self.buf.is_empty() {
114 self.buf.push('\n');
115 }
116 }
117
118 pub fn write(&mut self, s: &str) {
119 self.buf.push_str(s);
120 }
121
122 pub fn into_string(self) -> String {
123 self.buf
124 }
125
126 pub fn write_quoted(&mut self, s: &str) {
127 let mut has_newline = false;
128 let mut has_nonprintable = false;
129 for c in s.chars() {
130 match c {
131 '\n' => has_newline = true,
132 '\r' | '\t' | '\u{0020}'..='\u{FFFF}' => {}
133 _ => has_nonprintable = true,
134 }
135 }
136 if !has_newline || has_nonprintable {
137 use std::fmt::Write;
138 self.buf.push('"');
139 for c in s.chars() {
140 match c {
141 '\r' => self.write(r"\r"),
142 '\n' => self.write(r"\n"),
143 '\t' => self.write(r"\t"),
144 '"' => self.write("\\\""),
145 '\\' => self.write(r"\\"),
146 '\u{0020}'..='\u{FFFF}' => self.buf.push(c),
147 _ => write!(&mut self.buf, "\\u{:04}", c as u32).unwrap(),
148 }
149 }
150 self.buf.push('"');
151 } else {
152 self.buf.push_str(r#"""""#);
153 self.endline();
154 self.indent += self.style.indent;
155 for line in s.lines() {
156 if !line.trim().is_empty() {
157 self.indent();
158 self.write(&line.replace(r#"""""#, r#"\""""#));
159 }
160 self.endline();
161 }
162 self.indent -= self.style.indent;
163 self.indent();
164 self.buf.push_str(r#"""""#);
165 }
166 }
167
168 fn inc_indent(&mut self) {
169 self.indent += self.style.indent;
170 }
171
172 fn dec_indent(&mut self) {
173 self.indent = self
174 .indent
175 .checked_sub(self.style.indent)
176 .expect("negative indent");
177 }
178}
179
180pub(crate) fn format_directives<'a, T>(dirs: &[Directive<'a, T>], f: &mut Formatter)
181where
182 T: crate::common::Text<'a>,
183{
184 for dir in dirs {
185 f.write(" ");
186 dir.display(f);
187 }
188}
189
190macro_rules! impl_display {
191 ($( $typ: ident, )+) => {
192 $(
193 impl fmt::Display for $typ {
194 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
195 f.write_str(&to_string(self))
196 }
197 }
198 )+
199 };
200
201 ('a $($typ: ident, )+) => {
202 $(
203 impl<'a, T> fmt::Display for $typ<'a, T>
204 where T: Text<'a>,
205 {
206 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
207 f.write_str(&to_string(self))
208 }
209 }
210 )+
211 };
212}