1use std::fmt;
2
3use crate::common::Text;
4use crate::format::{format_directives, Displayable, Formatter, Style};
5
6use crate::schema::ast::*;
7
8impl<'a, T> Document<'a, T>
9where
10 T: Text<'a>,
11{
12 pub fn format(&self, style: &Style) -> String {
14 let mut formatter = Formatter::new(style);
15 self.display(&mut formatter);
16 formatter.into_string()
17 }
18}
19
20fn to_string<T: Displayable>(v: &T) -> String {
21 let style = Style::default();
22 let mut formatter = Formatter::new(&style);
23 v.display(&mut formatter);
24 formatter.into_string()
25}
26
27fn description(description: &Option<String>, f: &mut Formatter) {
28 if let Some(ref descr) = *description {
29 f.indent();
30 f.write_quoted(descr.as_ref());
31 f.endline();
32 }
33}
34
35impl<'a, T> Displayable for Document<'a, T>
36where
37 T: Text<'a>,
38{
39 fn display(&self, f: &mut Formatter) {
40 for item in &self.definitions {
41 item.display(f);
42 }
43 }
44}
45
46impl<'a, T> Displayable for Definition<'a, T>
47where
48 T: Text<'a>,
49{
50 fn display(&self, f: &mut Formatter) {
51 f.margin();
52 match *self {
53 Definition::SchemaDefinition(ref s) => s.display(f),
54 Definition::TypeDefinition(ref t) => t.display(f),
55 Definition::TypeExtension(ref e) => e.display(f),
56 Definition::DirectiveDefinition(ref d) => d.display(f),
57 }
58 }
59}
60
61impl<'a, T> Displayable for SchemaDefinition<'a, T>
62where
63 T: Text<'a>,
64{
65 fn display(&self, f: &mut Formatter) {
66 f.indent();
67 f.write("schema");
68 format_directives(&self.directives, f);
69 f.write(" ");
70 f.start_block();
71 if let Some(ref q) = self.query {
72 f.indent();
73 f.write("query: ");
74 f.write(q.as_ref());
75 f.endline();
76 }
77 if let Some(ref m) = self.mutation {
78 f.indent();
79 f.write("mutation: ");
80 f.write(m.as_ref());
81 f.endline();
82 }
83 if let Some(ref s) = self.subscription {
84 f.indent();
85 f.write("subscription: ");
86 f.write(s.as_ref());
87 f.endline();
88 }
89 f.end_block();
90 }
91}
92
93impl<'a, T> Displayable for TypeDefinition<'a, T>
94where
95 T: Text<'a>,
96{
97 fn display(&self, f: &mut Formatter) {
98 match *self {
99 TypeDefinition::Scalar(ref s) => s.display(f),
100 TypeDefinition::Object(ref o) => o.display(f),
101 TypeDefinition::Interface(ref i) => i.display(f),
102 TypeDefinition::Union(ref u) => u.display(f),
103 TypeDefinition::Enum(ref e) => e.display(f),
104 TypeDefinition::InputObject(ref i) => i.display(f),
105 }
106 }
107}
108
109impl<'a, T> Displayable for ScalarType<'a, T>
110where
111 T: Text<'a>,
112{
113 fn display(&self, f: &mut Formatter) {
114 description(&self.description, f);
115 f.indent();
116 f.write("scalar ");
117 f.write(self.name.as_ref());
118 format_directives(&self.directives, f);
119 f.endline();
120 }
121}
122
123impl<'a, T> Displayable for ScalarTypeExtension<'a, T>
124where
125 T: Text<'a>,
126{
127 fn display(&self, f: &mut Formatter) {
128 f.indent();
129 f.write("extend scalar ");
130 f.write(self.name.as_ref());
131 format_directives(&self.directives, f);
132 f.endline();
133 }
134}
135
136fn format_fields<'a, T>(fields: &[Field<'a, T>], f: &mut Formatter)
137where
138 T: Text<'a>,
139{
140 if !fields.is_empty() {
141 f.write(" ");
142 f.start_block();
143 for fld in fields {
144 fld.display(f);
145 }
146 f.end_block();
147 } else {
148 f.endline();
149 }
150}
151
152impl<'a, T> Displayable for ObjectType<'a, T>
153where
154 T: Text<'a>,
155{
156 fn display(&self, f: &mut Formatter) {
157 description(&self.description, f);
158 f.indent();
159 f.write("type ");
160 f.write(self.name.as_ref());
161 if !self.implements_interfaces.is_empty() {
162 f.write(" implements ");
163 f.write(self.implements_interfaces[0].as_ref());
164 for name in &self.implements_interfaces[1..] {
165 f.write(" & ");
166 f.write(name.as_ref());
167 }
168 }
169 format_directives(&self.directives, f);
170 format_fields(&self.fields, f);
171 }
172}
173
174impl<'a, T> Displayable for ObjectTypeExtension<'a, T>
175where
176 T: Text<'a>,
177{
178 fn display(&self, f: &mut Formatter) {
179 f.indent();
180 f.write("extend type ");
181 f.write(self.name.as_ref());
182 if !self.implements_interfaces.is_empty() {
183 f.write(" implements ");
184 f.write(self.implements_interfaces[0].as_ref());
185 for name in &self.implements_interfaces[1..] {
186 f.write(" & ");
187 f.write(name.as_ref());
188 }
189 }
190 format_directives(&self.directives, f);
191 format_fields(&self.fields, f);
192 }
193}
194
195impl<'a, T> Displayable for InputValue<'a, T>
196where
197 T: Text<'a>,
198{
199 fn display(&self, f: &mut Formatter) {
200 if let Some(ref descr) = self.description {
201 f.write_quoted(descr.as_ref());
202 f.write(" ");
203 }
204 f.write(self.name.as_ref());
205 f.write(": ");
206 self.value_type.display(f);
207 if let Some(ref def) = self.default_value {
208 f.write(" = ");
209 def.display(f);
210 }
211 format_directives(&self.directives, f);
212 }
213}
214
215fn format_arguments<'a, T>(arguments: &[InputValue<'a, T>], f: &mut Formatter)
216where
217 T: Text<'a>,
218{
219 if !arguments.is_empty() {
220 f.write("(");
221 arguments[0].display(f);
222 for arg in &arguments[1..] {
223 f.write(", ");
224 arg.display(f);
225 }
226 f.write(")");
227 }
228}
229
230impl<'a, T> Displayable for Field<'a, T>
231where
232 T: Text<'a>,
233{
234 fn display(&self, f: &mut Formatter) {
235 description(&self.description, f);
236 f.indent();
237 f.write(self.name.as_ref());
238 format_arguments(&self.arguments, f);
239 f.write(": ");
240 self.field_type.display(f);
241 format_directives(&self.directives, f);
242 f.endline();
243 }
244}
245
246impl<'a, T> Displayable for InterfaceType<'a, T>
247where
248 T: Text<'a>,
249{
250 fn display(&self, f: &mut Formatter) {
251 description(&self.description, f);
252 f.indent();
253 f.write("interface ");
254 f.write(self.name.as_ref());
255 if !self.implements_interfaces.is_empty() {
256 f.write(" implements ");
257 f.write(self.implements_interfaces[0].as_ref());
258 for name in &self.implements_interfaces[1..] {
259 f.write(" & ");
260 f.write(name.as_ref());
261 }
262 }
263 format_directives(&self.directives, f);
264 format_fields(&self.fields, f);
265 }
266}
267
268impl<'a, T> Displayable for InterfaceTypeExtension<'a, T>
269where
270 T: Text<'a>,
271{
272 fn display(&self, f: &mut Formatter) {
273 f.indent();
274 f.write("extend interface ");
275 f.write(self.name.as_ref());
276 if !self.implements_interfaces.is_empty() {
277 f.write(" implements ");
278 f.write(self.implements_interfaces[0].as_ref());
279 for name in &self.implements_interfaces[1..] {
280 f.write(" & ");
281 f.write(name.as_ref());
282 }
283 }
284 format_directives(&self.directives, f);
285 format_fields(&self.fields, f);
286 }
287}
288
289impl<'a, T> Displayable for UnionType<'a, T>
290where
291 T: Text<'a>,
292{
293 fn display(&self, f: &mut Formatter) {
294 description(&self.description, f);
295 f.indent();
296 f.write("union ");
297 f.write(self.name.as_ref());
298 format_directives(&self.directives, f);
299 if !self.types.is_empty() {
300 f.write(" = ");
301 f.write(self.types[0].as_ref());
302 for typ in &self.types[1..] {
303 f.write(" | ");
304 f.write(typ.as_ref());
305 }
306 }
307 f.endline();
308 }
309}
310
311impl<'a, T> Displayable for UnionTypeExtension<'a, T>
312where
313 T: Text<'a>,
314{
315 fn display(&self, f: &mut Formatter) {
316 f.indent();
317 f.write("extend union ");
318 f.write(self.name.as_ref());
319 format_directives(&self.directives, f);
320 if !self.types.is_empty() {
321 f.write(" = ");
322 f.write(self.types[0].as_ref());
323 for typ in &self.types[1..] {
324 f.write(" | ");
325 f.write(typ.as_ref());
326 }
327 }
328 f.endline();
329 }
330}
331
332impl<'a, T> Displayable for EnumType<'a, T>
333where
334 T: Text<'a>,
335{
336 fn display(&self, f: &mut Formatter) {
337 description(&self.description, f);
338 f.indent();
339 f.write("enum ");
340 f.write(self.name.as_ref());
341 format_directives(&self.directives, f);
342 if !self.values.is_empty() {
343 f.write(" ");
344 f.start_block();
345 for val in &self.values {
346 f.indent();
347 if let Some(ref descr) = val.description {
348 f.write_quoted(descr.as_ref());
349 f.write(" ");
350 }
351 f.write(val.name.as_ref());
352 format_directives(&val.directives, f);
353 f.endline();
354 }
355 f.end_block();
356 } else {
357 f.endline();
358 }
359 }
360}
361
362impl<'a, T> Displayable for EnumTypeExtension<'a, T>
363where
364 T: Text<'a>,
365{
366 fn display(&self, f: &mut Formatter) {
367 f.indent();
368 f.write("extend enum ");
369 f.write(self.name.as_ref());
370 format_directives(&self.directives, f);
371 if !self.values.is_empty() {
372 f.write(" ");
373 f.start_block();
374 for val in &self.values {
375 f.indent();
376 if let Some(ref descr) = val.description {
377 f.write_quoted(descr.as_ref());
378 f.write(" ");
379 }
380 f.write(val.name.as_ref());
381 format_directives(&val.directives, f);
382 f.endline();
383 }
384 f.end_block();
385 } else {
386 f.endline();
387 }
388 }
389}
390
391fn format_inputs<'a, T>(fields: &[InputValue<'a, T>], f: &mut Formatter)
392where
393 T: Text<'a>,
394{
395 if !fields.is_empty() {
396 f.write(" ");
397 f.start_block();
398 for fld in fields {
399 f.indent();
400 fld.display(f);
401 f.endline();
402 }
403 f.end_block();
404 } else {
405 f.endline();
406 }
407}
408
409impl<'a, T> Displayable for InputObjectType<'a, T>
410where
411 T: Text<'a>,
412{
413 fn display(&self, f: &mut Formatter) {
414 description(&self.description, f);
415 f.indent();
416 f.write("input ");
417 f.write(self.name.as_ref());
418 format_directives(&self.directives, f);
419 format_inputs(&self.fields, f);
420 }
421}
422
423impl<'a, T> Displayable for InputObjectTypeExtension<'a, T>
424where
425 T: Text<'a>,
426{
427 fn display(&self, f: &mut Formatter) {
428 f.indent();
429 f.write("extend input ");
430 f.write(self.name.as_ref());
431 format_directives(&self.directives, f);
432 format_inputs(&self.fields, f);
433 }
434}
435
436impl<'a, T> Displayable for TypeExtension<'a, T>
437where
438 T: Text<'a>,
439{
440 fn display(&self, f: &mut Formatter) {
441 match *self {
442 TypeExtension::Scalar(ref s) => s.display(f),
443 TypeExtension::Object(ref o) => o.display(f),
444 TypeExtension::Interface(ref i) => i.display(f),
445 TypeExtension::Union(ref u) => u.display(f),
446 TypeExtension::Enum(ref e) => e.display(f),
447 TypeExtension::InputObject(ref i) => i.display(f),
448 }
449 }
450}
451
452impl<'a, T> Displayable for DirectiveDefinition<'a, T>
453where
454 T: Text<'a>,
455{
456 fn display(&self, f: &mut Formatter) {
457 description(&self.description, f);
458 f.indent();
459 f.write("directive @");
460 f.write(self.name.as_ref());
461 format_arguments(&self.arguments, f);
462 if self.repeatable {
463 f.write(" repeatable");
464 }
465 if !self.locations.is_empty() {
466 f.write(" on ");
467 let mut first = true;
468 for loc in &self.locations {
469 if first {
470 first = false;
471 } else {
472 f.write(" | ");
473 }
474 f.write(loc.as_str());
475 }
476 }
477 f.endline();
478 }
479}
480
481impl_display!(
482 'a
483 Document,
484 Definition,
485 SchemaDefinition,
486 TypeDefinition,
487 TypeExtension,
488 ScalarType,
489 ScalarTypeExtension,
490 ObjectType,
491 ObjectTypeExtension,
492 Field,
493 InputValue,
494 InterfaceType,
495 InterfaceTypeExtension,
496 UnionType,
497 UnionTypeExtension,
498 EnumType,
499 EnumTypeExtension,
500 InputObjectType,
501 InputObjectTypeExtension,
502 DirectiveDefinition,
503);