1use std::fmt;
2
3use crate::format::{format_directives, Displayable, Formatter, Style};
4
5use crate::query::ast::*;
6
7impl<'a, T: Text<'a>> Document<'a, T>
8where
9 T: Text<'a>,
10{
11 pub fn format(&self, style: &Style) -> String {
13 let mut formatter = Formatter::new(style);
14 self.display(&mut formatter);
15 formatter.into_string()
16 }
17}
18
19fn to_string<T: Displayable>(v: &T) -> String {
20 let style = Style::default();
21 let mut formatter = Formatter::new(&style);
22 v.display(&mut formatter);
23 formatter.into_string()
24}
25
26impl<'a, T: Text<'a>> Displayable for Document<'a, T>
27where
28 T: Text<'a>,
29{
30 fn display(&self, f: &mut Formatter) {
31 for item in &self.definitions {
32 item.display(f);
33 }
34 }
35}
36
37impl<'a, T: Text<'a>> Displayable for Definition<'a, T>
38where
39 T: Text<'a>,
40{
41 fn display(&self, f: &mut Formatter) {
42 match *self {
43 Definition::Operation(ref op) => op.display(f),
44 Definition::Fragment(ref frag) => frag.display(f),
45 }
46 }
47}
48
49impl<'a, T: Text<'a>> Displayable for OperationDefinition<'a, T>
50where
51 T: Text<'a>,
52{
53 fn display(&self, f: &mut Formatter) {
54 match *self {
55 OperationDefinition::SelectionSet(ref set) => set.display(f),
56 OperationDefinition::Query(ref q) => q.display(f),
57 OperationDefinition::Mutation(ref m) => m.display(f),
58 OperationDefinition::Subscription(ref s) => s.display(f),
59 }
60 }
61}
62
63impl<'a, T: Text<'a>> Displayable for FragmentDefinition<'a, T>
64where
65 T: Text<'a>,
66{
67 fn display(&self, f: &mut Formatter) {
68 f.margin();
69 f.indent();
70 f.write("fragment ");
71 f.write(self.name.as_ref());
72 f.write(" ");
73 self.type_condition.display(f);
74 format_directives(&self.directives, f);
75 f.write(" ");
76 f.start_block();
77 for item in &self.selection_set.items {
78 item.display(f);
79 }
80 f.end_block();
81 }
82}
83
84impl<'a, T: Text<'a>> Displayable for SelectionSet<'a, T>
85where
86 T: Text<'a>,
87{
88 fn display(&self, f: &mut Formatter) {
89 f.margin();
90 f.indent();
91 f.start_block();
92 for item in &self.items {
93 item.display(f);
94 }
95 f.end_block();
96 }
97}
98
99impl<'a, T: Text<'a>> Displayable for Selection<'a, T>
100where
101 T: Text<'a>,
102{
103 fn display(&self, f: &mut Formatter) {
104 match *self {
105 Selection::Field(ref fld) => fld.display(f),
106 Selection::InlineFragment(ref frag) => frag.display(f),
107 Selection::FragmentSpread(ref frag) => frag.display(f),
108 }
109 }
110}
111
112fn format_arguments<'a, T: Text<'a>>(arguments: &[(T::Value, Value<'a, T>)], f: &mut Formatter)
113where
114 T: Text<'a>,
115{
116 if !arguments.is_empty() {
117 f.start_argument_block('(');
118 f.start_argument();
119 f.write(arguments[0].0.as_ref());
120 f.write(": ");
121 arguments[0].1.display(f);
122 for arg in &arguments[1..] {
123 f.deliniate_argument();
124 f.start_argument();
125 f.write(arg.0.as_ref());
126 f.write(": ");
127 arg.1.display(f);
128 }
129 f.end_argument_block(')');
130 }
131}
132
133impl<'a, T: Text<'a>> Displayable for Field<'a, T>
134where
135 T: Text<'a>,
136{
137 fn display(&self, f: &mut Formatter) {
138 f.indent();
139 if let Some(ref alias) = self.alias {
140 f.write(alias.as_ref());
141 f.write(": ");
142 }
143 f.write(self.name.as_ref());
144 format_arguments(&self.arguments, f);
145 format_directives(&self.directives, f);
146 if !self.selection_set.items.is_empty() {
147 f.write(" ");
148 f.start_block();
149 for item in &self.selection_set.items {
150 item.display(f);
151 }
152 f.end_block();
153 } else {
154 f.endline();
155 }
156 }
157}
158
159impl<'a, T: Text<'a>> Displayable for Query<'a, T>
160where
161 T: Text<'a>,
162{
163 fn display(&self, f: &mut Formatter) {
164 f.margin();
165 f.indent();
166 f.write("query");
167 if let Some(ref name) = self.name {
168 f.write(" ");
169 f.write(name.as_ref());
170 }
171 if !self.variable_definitions.is_empty() {
172 f.write("(");
173 self.variable_definitions[0].display(f);
174 for var in &self.variable_definitions[1..] {
175 f.write(", ");
176 var.display(f);
177 }
178 f.write(")");
179 }
180 format_directives(&self.directives, f);
181 f.write(" ");
182 f.start_block();
183 for item in &self.selection_set.items {
184 item.display(f);
185 }
186 f.end_block();
187 }
188}
189
190impl<'a, T: Text<'a>> Displayable for Mutation<'a, T>
191where
192 T: Text<'a>,
193{
194 fn display(&self, f: &mut Formatter) {
195 f.margin();
196 f.indent();
197 f.write("mutation");
198 if let Some(ref name) = self.name {
199 f.write(" ");
200 f.write(name.as_ref());
201 }
202 if !self.variable_definitions.is_empty() {
203 f.write("(");
204 self.variable_definitions[0].display(f);
205 for var in &self.variable_definitions[1..] {
206 f.write(", ");
207 var.display(f);
208 }
209 f.write(")");
210 }
211 format_directives(&self.directives, f);
212 f.write(" ");
213 f.start_block();
214 for item in &self.selection_set.items {
215 item.display(f);
216 }
217 f.end_block();
218 }
219}
220
221impl<'a, T: Text<'a>> Displayable for Subscription<'a, T>
222where
223 T: Text<'a>,
224{
225 fn display(&self, f: &mut Formatter) {
226 f.margin();
227 f.indent();
228 f.write("subscription");
229 if let Some(ref name) = self.name {
230 f.write(" ");
231 f.write(name.as_ref());
232 if !self.variable_definitions.is_empty() {
233 f.write("(");
234 for var in &self.variable_definitions {
235 var.display(f);
236 }
237 f.write(")");
238 }
239 }
240 format_directives(&self.directives, f);
241 f.write(" ");
242 f.start_block();
243 for item in &self.selection_set.items {
244 item.display(f);
245 }
246 f.end_block();
247 }
248}
249
250impl<'a, T: Text<'a>> Displayable for VariableDefinition<'a, T>
251where
252 T: Text<'a>,
253{
254 fn display(&self, f: &mut Formatter) {
255 f.write("$");
256 f.write(self.name.as_ref());
257 f.write(": ");
258 self.var_type.display(f);
259 if let Some(ref default) = self.default_value {
260 f.write(" = ");
261 default.display(f);
262 }
263 }
264}
265
266impl<'a, T: Text<'a>> Displayable for Type<'a, T>
267where
268 T: Text<'a>,
269{
270 fn display(&self, f: &mut Formatter) {
271 match *self {
272 Type::NamedType(ref name) => f.write(name.as_ref()),
273 Type::ListType(ref typ) => {
274 f.write("[");
275 typ.display(f);
276 f.write("]");
277 }
278 Type::NonNullType(ref typ) => {
279 typ.display(f);
280 f.write("!");
281 }
282 }
283 }
284}
285
286impl<'a, T: Text<'a>> Displayable for Value<'a, T>
287where
288 T: Text<'a>,
289{
290 fn display(&self, f: &mut Formatter) {
291 match *self {
292 Value::Variable(ref name) => {
293 f.write("$");
294 f.write(name.as_ref());
295 }
296 Value::Int(ref num) => f.write(&format!("{}", num.0)),
297 Value::Float(val) => f.write(&format!("{}", val)),
298 Value::String(ref val) => f.write_quoted(val),
299 Value::Boolean(true) => f.write("true"),
300 Value::Boolean(false) => f.write("false"),
301 Value::Null => f.write("null"),
302 Value::Enum(ref name) => f.write(name.as_ref()),
303 Value::List(ref items) => {
304 f.start_argument_block('[');
305 if !items.is_empty() {
306 f.start_argument();
307 items[0].display(f);
308 for item in &items[1..] {
309 f.deliniate_argument();
310 f.start_argument();
311 item.display(f);
312 }
313 }
314 f.end_argument_block(']');
315 }
316 Value::Object(ref items) => {
317 f.start_argument_block('{');
318 let mut first = true;
319 for (name, value) in items.iter() {
320 if first {
321 first = false;
322 } else {
323 f.deliniate_argument();
324 }
325 f.start_argument();
326 f.write(name.as_ref());
327 f.write(": ");
328 value.display(f);
329 }
330 f.end_argument_block('}');
331 }
332 }
333 }
334}
335
336impl<'a, T: Text<'a>> Displayable for InlineFragment<'a, T>
337where
338 T: Text<'a>,
339{
340 fn display(&self, f: &mut Formatter) {
341 f.indent();
342 f.write("...");
343 if let Some(ref cond) = self.type_condition {
344 f.write(" ");
345 cond.display(f);
346 }
347 format_directives(&self.directives, f);
348 f.write(" ");
349 f.start_block();
350 for item in &self.selection_set.items {
351 item.display(f);
352 }
353 f.end_block();
354 }
355}
356
357impl<'a, T: Text<'a>> Displayable for TypeCondition<'a, T>
358where
359 T: Text<'a>,
360{
361 fn display(&self, f: &mut Formatter) {
362 match *self {
363 TypeCondition::On(ref name) => {
364 f.write("on ");
365 f.write(name.as_ref());
366 }
367 }
368 }
369}
370
371impl<'a, T: Text<'a>> Displayable for FragmentSpread<'a, T>
372where
373 T: Text<'a>,
374{
375 fn display(&self, f: &mut Formatter) {
376 f.indent();
377 f.write("...");
378 f.write(self.fragment_name.as_ref());
379 format_directives(&self.directives, f);
380 f.endline();
381 }
382}
383
384impl<'a, T: Text<'a>> Displayable for Directive<'a, T>
385where
386 T: Text<'a>,
387{
388 fn display(&self, f: &mut Formatter) {
389 f.write("@");
390 f.write(self.name.as_ref());
391 format_arguments(self.arguments.as_slice(), f);
392 }
393}
394
395impl_display!(
396 'a
397 Document,
398 Definition,
399 OperationDefinition,
400 FragmentDefinition,
401 SelectionSet,
402 Field,
403 Query,
404 Mutation,
405 Subscription,
406 VariableDefinition,
407 Type,
408 Value,
409 InlineFragment,
410 TypeCondition,
411 FragmentSpread,
412 Directive,
413);