1use super::*;
2use crate::executable;
3use crate::schema;
4use std::fmt;
5use std::fmt::Display;
6
7#[derive(Debug, Clone)]
10pub struct Serialize<'a, T> {
11 pub(crate) node: &'a T,
12 pub(crate) config: Config<'a>,
13}
14
15#[derive(Debug, Clone)]
16pub(crate) struct Config<'a> {
17 indent_prefix: Option<&'a str>,
18 initial_indent_level: usize,
19}
20
21pub(crate) struct State<'config, 'fmt, 'fmt2> {
22 config: Config<'config>,
23 indent_level: usize,
24 output: &'fmt mut fmt::Formatter<'fmt2>,
25 output_empty: bool,
27}
28
29impl<'a, T> Serialize<'a, T> {
30 pub fn indent_prefix(mut self, prefix: &'a str) -> Self {
35 self.config.indent_prefix = Some(prefix);
36 self
37 }
38
39 pub fn no_indent(mut self) -> Self {
41 self.config.indent_prefix = None;
42 self
43 }
44
45 pub fn initial_indent_level(mut self, initial_indent_level: usize) -> Self {
46 self.config.initial_indent_level = initial_indent_level;
47 self
48 }
49}
50
51impl Default for Config<'_> {
52 fn default() -> Self {
53 Self {
54 indent_prefix: Some(" "),
55 initial_indent_level: 0,
56 }
57 }
58}
59
60macro_rules! display {
61 ($state: expr, $e: expr) => {
62 fmt::Display::fmt(&$e, $state.output)
63 };
64 ($state: expr, $($tt: tt)+) => {
65 display!($state, format_args!($($tt)+))
66 };
67
68}
69
70impl State<'_, '_, '_> {
71 pub(crate) fn write(&mut self, str: &str) -> fmt::Result {
72 self.output_empty = false;
73 self.output.write_str(str)
74 }
75
76 pub(crate) fn indent(&mut self) -> fmt::Result {
77 self.indent_level += 1;
78 self.new_line_common(false)
79 }
80
81 pub(crate) fn indent_or_space(&mut self) -> fmt::Result {
82 self.indent_level += 1;
83 self.new_line_common(true)
84 }
85
86 pub(crate) fn dedent(&mut self) -> fmt::Result {
87 self.indent_level -= 1; self.new_line_common(false)
89 }
90
91 pub(crate) fn dedent_or_space(&mut self) -> fmt::Result {
92 self.indent_level -= 1; self.new_line_common(true)
94 }
95
96 pub(crate) fn new_line_or_space(&mut self) -> fmt::Result {
97 self.new_line_common(true)
98 }
99
100 fn new_line_common(&mut self, space: bool) -> fmt::Result {
101 if let Some(prefix) = self.config.indent_prefix {
102 self.write("\n")?;
103 for _ in 0..self.indent_level {
104 self.write(prefix)?;
105 }
106 } else if space {
107 self.write(" ")?
108 }
109 Ok(())
110 }
111
112 fn require_new_line(&mut self) -> fmt::Result {
114 let prefix = self
115 .config
116 .indent_prefix
117 .expect("require_new_line called with newlines disabled");
118 self.write("\n")?;
119 for _ in 0..self.indent_level {
120 self.write(prefix)?;
121 }
122 Ok(())
123 }
124
125 pub(crate) fn newlines_enabled(&self) -> bool {
126 self.config.indent_prefix.is_some()
127 }
128
129 pub(crate) fn on_single_line<R>(&mut self, f: impl FnOnce(&mut Self) -> R) -> R {
130 let indent_prefix = self.config.indent_prefix.take();
131 let result = f(self);
132 self.config.indent_prefix = indent_prefix;
133 result
134 }
135}
136
137impl Document {
138 pub(crate) fn serialize_impl(&self, state: &mut State) -> fmt::Result {
139 top_level(state, &self.definitions, |state, def| {
140 def.serialize_impl(state)
141 })
142 }
143}
144
145pub(crate) fn top_level<T>(
146 state: &mut State,
147 iter: impl IntoIterator<Item = T>,
148 serialize_one: impl Fn(&mut State, T) -> fmt::Result,
149) -> fmt::Result {
150 let mut iter = iter.into_iter();
151 if let Some(first) = iter.next() {
152 serialize_one(state, first)?;
153 iter.try_for_each(|item| {
154 if state.newlines_enabled() {
155 state.write("\n")?;
157 }
158 state.new_line_or_space()?;
159 serialize_one(state, item)
160 })?;
161 if state.newlines_enabled() {
163 state.write("\n")?;
164 }
165 }
166 Ok(())
167}
168
169impl Definition {
170 pub(crate) fn serialize_impl(&self, state: &mut State) -> fmt::Result {
171 match self {
172 Definition::OperationDefinition(def) => def.serialize_impl(state),
173 Definition::FragmentDefinition(def) => def.serialize_impl(state),
174 Definition::DirectiveDefinition(def) => def.serialize_impl(state),
175 Definition::SchemaDefinition(def) => def.serialize_impl(state),
176 Definition::ScalarTypeDefinition(def) => def.serialize_impl(state),
177 Definition::ObjectTypeDefinition(def) => def.serialize_impl(state),
178 Definition::InterfaceTypeDefinition(def) => def.serialize_impl(state),
179 Definition::UnionTypeDefinition(def) => def.serialize_impl(state),
180 Definition::EnumTypeDefinition(def) => def.serialize_impl(state),
181 Definition::InputObjectTypeDefinition(def) => def.serialize_impl(state),
182 Definition::SchemaExtension(def) => def.serialize_impl(state),
183 Definition::ScalarTypeExtension(def) => def.serialize_impl(state),
184 Definition::ObjectTypeExtension(def) => def.serialize_impl(state),
185 Definition::InterfaceTypeExtension(def) => def.serialize_impl(state),
186 Definition::UnionTypeExtension(def) => def.serialize_impl(state),
187 Definition::EnumTypeExtension(def) => def.serialize_impl(state),
188 Definition::InputObjectTypeExtension(def) => def.serialize_impl(state),
189 }
190 }
191}
192
193impl OperationDefinition {
194 fn serialize_impl(&self, state: &mut State) -> fmt::Result {
195 let Self {
197 operation_type,
198 name,
199 variables,
200 directives,
201 selection_set,
202 } = self;
203 let shorthand = state.output_empty
206 && *operation_type == OperationType::Query
207 && name.is_none()
208 && variables.is_empty()
209 && directives.is_empty();
210 if !shorthand {
211 state.write(operation_type.name())?;
212 if let Some(name) = &name {
213 state.write(" ")?;
214 state.write(name)?;
215 }
216 if !variables.is_empty() {
217 state.on_single_line(|state| {
218 comma_separated(state, "(", ")", variables, |state, var| {
219 var.serialize_impl(state)
220 })
221 })?
222 }
223 directives.serialize_impl(state)?;
224 state.write(" ")?;
225 }
226 curly_brackets_space_separated(state, selection_set, |state, sel| sel.serialize_impl(state))
227 }
228}
229
230impl FragmentDefinition {
231 fn serialize_impl(&self, state: &mut State) -> fmt::Result {
232 let Self {
233 name,
234 type_condition,
235 directives,
236 selection_set,
237 } = self;
238 display!(state, "fragment {} on {}", name, type_condition)?;
239 directives.serialize_impl(state)?;
240 state.write(" ")?;
241 curly_brackets_space_separated(state, selection_set, |state, sel| sel.serialize_impl(state))
242 }
243}
244
245impl DirectiveDefinition {
246 fn serialize_impl(&self, state: &mut State) -> fmt::Result {
247 let Self {
248 description,
249 name,
250 arguments,
251 repeatable,
252 locations,
253 } = self;
254 serialize_description(state, description)?;
255 state.write("directive @")?;
256 state.write(name)?;
257 serialize_arguments_definition(state, arguments)?;
258
259 if *repeatable {
260 state.write(" repeatable")?;
261 }
262 if let Some((first, rest)) = locations.split_first() {
263 state.write(" on ")?;
264 state.write(first.name())?;
265 for location in rest {
266 state.write(" | ")?;
267 state.write(location.name())?;
268 }
269 }
270 Ok(())
271 }
272}
273
274fn serialize_arguments_definition(
275 state: &mut State,
276 arguments: &[Node<InputValueDefinition>],
277) -> fmt::Result {
278 if !arguments.is_empty() {
279 let serialize_arguments = |state: &mut State| {
280 comma_separated(state, "(", ")", arguments, |state, arg| {
281 arg.serialize_impl(state)
282 })
283 };
284 if arguments
285 .iter()
286 .any(|arg| arg.description.is_some() || !arg.directives.is_empty())
287 {
288 serialize_arguments(state)?
289 } else {
290 state.on_single_line(serialize_arguments)?
291 }
292 }
293 Ok(())
294}
295
296impl SchemaDefinition {
297 fn serialize_impl(&self, state: &mut State) -> fmt::Result {
298 let Self {
299 description,
300 directives,
301 root_operations,
302 } = self;
303 serialize_description(state, description)?;
304 state.write("schema")?;
305 directives.serialize_impl(state)?;
306 state.write(" ")?;
307 curly_brackets_space_separated(state, root_operations, |state, op| {
308 let (operation_type, operation_name) = &**op;
309 display!(state, "{}: {}", operation_type, operation_name)
310 })
311 }
312}
313
314impl ScalarTypeDefinition {
315 fn serialize_impl(&self, state: &mut State) -> fmt::Result {
316 let Self {
317 description,
318 name,
319 directives,
320 } = self;
321 serialize_description(state, description)?;
322 state.write("scalar ")?;
323 state.write(name)?;
324 directives.serialize_impl(state)
325 }
326}
327
328impl ObjectTypeDefinition {
329 fn serialize_impl(&self, state: &mut State) -> fmt::Result {
330 let Self {
331 description,
332 name,
333 implements_interfaces,
334 directives,
335 fields,
336 } = self;
337 serialize_description(state, description)?;
338 state.write("type ")?;
339 serialize_object_type_like(state, name, implements_interfaces, directives, fields)
340 }
341}
342
343fn serialize_object_type_like(
344 state: &mut State,
345 name: &str,
346 implements_interfaces: &[Name],
347 directives: &DirectiveList,
348 fields: &[Node<FieldDefinition>],
349) -> Result<(), fmt::Error> {
350 state.write(name)?;
351 if let Some((first, rest)) = implements_interfaces.split_first() {
352 state.write(" implements ")?;
353 state.write(first)?;
354 for name in rest {
355 state.write(" & ")?;
356 state.write(name)?;
357 }
358 }
359 directives.serialize_impl(state)?;
360
361 if !fields.is_empty() {
362 state.write(" ")?;
363 curly_brackets_space_separated(state, fields, |state, field| field.serialize_impl(state))?;
364 }
365 Ok(())
366}
367
368impl InterfaceTypeDefinition {
369 fn serialize_impl(&self, state: &mut State) -> fmt::Result {
370 let Self {
371 description,
372 name,
373 implements_interfaces,
374 directives,
375 fields,
376 } = self;
377 serialize_description(state, description)?;
378 state.write("interface ")?;
379 serialize_object_type_like(state, name, implements_interfaces, directives, fields)
380 }
381}
382
383impl UnionTypeDefinition {
384 fn serialize_impl(&self, state: &mut State) -> fmt::Result {
385 let Self {
386 description,
387 name,
388 directives,
389 members,
390 } = self;
391 serialize_description(state, description)?;
392 state.write("union ")?;
393 serialize_union(state, name, directives, members)
394 }
395}
396
397fn serialize_union(
398 state: &mut State,
399 name: &str,
400 directives: &DirectiveList,
401 members: &[Name],
402) -> fmt::Result {
403 state.write(name)?;
404 directives.serialize_impl(state)?;
405 if let Some((first, rest)) = members.split_first() {
406 state.write(" = ")?;
407 state.write(first)?;
408 for member in rest {
409 state.write(" | ")?;
410 state.write(member)?;
411 }
412 }
413 Ok(())
414}
415
416impl EnumTypeDefinition {
417 fn serialize_impl(&self, state: &mut State) -> fmt::Result {
418 let Self {
419 description,
420 name,
421 directives,
422 values,
423 } = self;
424 serialize_description(state, description)?;
425 state.write("enum ")?;
426 state.write(name)?;
427 directives.serialize_impl(state)?;
428 if !values.is_empty() {
429 state.write(" ")?;
430 curly_brackets_space_separated(state, values, |state, value| {
431 value.serialize_impl(state)
432 })?;
433 }
434 Ok(())
435 }
436}
437
438impl InputObjectTypeDefinition {
439 fn serialize_impl(&self, state: &mut State) -> fmt::Result {
440 let Self {
441 description,
442 name,
443 directives,
444 fields,
445 } = self;
446 serialize_description(state, description)?;
447 state.write("input ")?;
448 state.write(name)?;
449 directives.serialize_impl(state)?;
450 if !fields.is_empty() {
451 state.write(" ")?;
452 curly_brackets_space_separated(state, fields, |state, f| f.serialize_impl(state))?;
453 }
454 Ok(())
455 }
456}
457
458impl SchemaExtension {
459 fn serialize_impl(&self, state: &mut State) -> fmt::Result {
460 let Self {
461 directives,
462 root_operations,
463 } = self;
464 state.write("extend schema")?;
465 directives.serialize_impl(state)?;
466 if !root_operations.is_empty() {
467 state.write(" ")?;
468 curly_brackets_space_separated(state, root_operations, |state, op| {
469 let (operation_type, operation_name) = &**op;
470 display!(state, "{}: {}", operation_type, operation_name)
471 })?;
472 }
473 Ok(())
474 }
475}
476
477impl ScalarTypeExtension {
478 fn serialize_impl(&self, state: &mut State) -> fmt::Result {
479 let Self { name, directives } = self;
480 state.write("extend scalar ")?;
481 state.write(name)?;
482 directives.serialize_impl(state)
483 }
484}
485
486impl ObjectTypeExtension {
487 fn serialize_impl(&self, state: &mut State) -> fmt::Result {
488 let Self {
489 name,
490 implements_interfaces,
491 directives,
492 fields,
493 } = self;
494 state.write("extend type ")?;
495 serialize_object_type_like(state, name, implements_interfaces, directives, fields)
496 }
497}
498
499impl InterfaceTypeExtension {
500 fn serialize_impl(&self, state: &mut State) -> fmt::Result {
501 let Self {
502 name,
503 implements_interfaces,
504 directives,
505 fields,
506 } = self;
507 state.write("extend interface ")?;
508 serialize_object_type_like(state, name, implements_interfaces, directives, fields)
509 }
510}
511
512impl UnionTypeExtension {
513 fn serialize_impl(&self, state: &mut State) -> fmt::Result {
514 let Self {
515 name,
516 directives,
517 members,
518 } = self;
519 state.write("extend union ")?;
520 serialize_union(state, name, directives, members)
521 }
522}
523
524impl EnumTypeExtension {
525 fn serialize_impl(&self, state: &mut State) -> fmt::Result {
526 let Self {
527 name,
528 directives,
529 values,
530 } = self;
531 state.write("extend enum ")?;
532 state.write(name)?;
533 directives.serialize_impl(state)?;
534 if !values.is_empty() {
535 state.write(" ")?;
536 curly_brackets_space_separated(state, values, |state, value| {
537 value.serialize_impl(state)
538 })?;
539 }
540 Ok(())
541 }
542}
543
544impl InputObjectTypeExtension {
545 fn serialize_impl(&self, state: &mut State) -> fmt::Result {
546 let Self {
547 name,
548 directives,
549 fields,
550 } = self;
551 state.write("extend input ")?;
552 state.write(name)?;
553 directives.serialize_impl(state)?;
554 if !fields.is_empty() {
555 state.write(" ")?;
556 curly_brackets_space_separated(state, fields, |state, f| f.serialize_impl(state))?;
557 }
558 Ok(())
559 }
560}
561
562impl DirectiveList {
563 fn serialize_impl(&self, state: &mut State) -> fmt::Result {
564 for dir in self {
565 state.write(" ")?;
566 dir.serialize_impl(state)?;
567 }
568 Ok(())
569 }
570}
571
572impl Directive {
573 pub(crate) fn serialize_impl(&self, state: &mut State) -> fmt::Result {
574 let Self { name, arguments } = self;
575 state.write("@")?;
576 state.write(name)?;
577 serialize_arguments(state, arguments)
578 }
579}
580
581impl VariableDefinition {
582 fn serialize_impl(&self, state: &mut State) -> fmt::Result {
583 let Self {
584 name,
585 ty,
586 default_value,
587 directives,
588 } = self;
589 state.write("$")?;
590 state.write(name)?;
591 state.write(": ")?;
592 display!(state, ty)?;
593 if let Some(value) = default_value {
594 state.write(" = ")?;
595 value.serialize_impl(state)?
596 }
597 directives.serialize_impl(state)
598 }
599}
600
601impl FieldDefinition {
602 fn serialize_impl(&self, state: &mut State) -> fmt::Result {
603 let Self {
604 description,
605 name,
606 arguments,
607 ty,
608 directives,
609 } = self;
610 serialize_description(state, description)?;
611 state.write(name)?;
612 serialize_arguments_definition(state, arguments)?;
613 state.write(": ")?;
614 display!(state, ty)?;
615 directives.serialize_impl(state)
616 }
617}
618
619impl InputValueDefinition {
620 fn serialize_impl(&self, state: &mut State) -> fmt::Result {
621 let Self {
622 description,
623 name,
624 ty,
625 default_value,
626 directives,
627 } = self;
628 serialize_description(state, description)?;
629 state.write(name)?;
630 state.write(": ")?;
631 display!(state, ty)?;
632 if let Some(value) = default_value {
633 state.write(" = ")?;
634 value.serialize_impl(state)?
635 }
636 directives.serialize_impl(state)
637 }
638}
639
640impl EnumValueDefinition {
641 fn serialize_impl(&self, state: &mut State) -> fmt::Result {
642 let Self {
643 description,
644 value,
645 directives,
646 } = self;
647 serialize_description(state, description)?;
648 state.write(value)?;
649 directives.serialize_impl(state)
650 }
651}
652
653impl Selection {
654 pub(crate) fn serialize_impl(&self, state: &mut State) -> fmt::Result {
655 match self {
656 Selection::Field(x) => x.serialize_impl(state),
657 Selection::FragmentSpread(x) => x.serialize_impl(state),
658 Selection::InlineFragment(x) => x.serialize_impl(state),
659 }
660 }
661}
662
663impl Field {
664 pub(crate) fn serialize_impl(&self, state: &mut State) -> fmt::Result {
665 let Self {
666 alias,
667 name,
668 arguments,
669 directives,
670 selection_set,
671 } = self;
672 if let Some(alias) = alias {
673 state.write(alias)?;
674 state.write(": ")?;
675 }
676 state.write(name)?;
677 serialize_arguments(state, arguments)?;
678 directives.serialize_impl(state)?;
679 if !selection_set.is_empty() {
680 state.write(" ")?;
681 curly_brackets_space_separated(state, selection_set, |state, sel| {
682 sel.serialize_impl(state)
683 })?
684 }
685 Ok(())
686 }
687}
688
689impl FragmentSpread {
690 pub(crate) fn serialize_impl(&self, state: &mut State) -> fmt::Result {
691 let Self {
692 fragment_name,
693 directives,
694 } = self;
695 state.write("...")?;
696 state.write(fragment_name)?;
697 directives.serialize_impl(state)
698 }
699}
700
701impl InlineFragment {
702 pub(crate) fn serialize_impl(&self, state: &mut State) -> fmt::Result {
703 let Self {
704 type_condition,
705 directives,
706 selection_set,
707 } = self;
708 if let Some(type_name) = type_condition {
709 state.write("... on ")?;
710 state.write(type_name)?;
711 } else {
712 state.write("...")?;
713 }
714 directives.serialize_impl(state)?;
715 state.write(" ")?;
716 curly_brackets_space_separated(state, selection_set, |state, sel| sel.serialize_impl(state))
717 }
718}
719
720impl Value {
721 fn serialize_impl(&self, state: &mut State) -> fmt::Result {
722 match self {
723 Value::Null => state.write("null"),
724 Value::Boolean(true) => state.write("true"),
725 Value::Boolean(false) => state.write("false"),
726 Value::Enum(name) => state.write(name),
727 Value::String(value) => {
728 let is_description = false;
729 serialize_string_value(state, is_description, value)
730 }
731 Value::Variable(name) => display!(state, "${}", name),
732 Value::Float(value) => display!(state, value),
733 Value::Int(value) => display!(state, value),
734 Value::List(value) => comma_separated(state, "[", "]", value, |state, value| {
735 value.serialize_impl(state)
736 }),
737 Value::Object(value) => {
738 comma_separated(state, "{", "}", value, |state, (name, value)| {
739 state.write(name)?;
740 state.write(": ")?;
741 value.serialize_impl(state)
742 })
743 }
744 }
745 }
746}
747
748impl Argument {
749 fn serialize_impl(&self, state: &mut State) -> fmt::Result {
750 state.write(&self.name)?;
751 state.write(": ")?;
752 self.value.serialize_impl(state)
753 }
754}
755
756fn serialize_arguments(state: &mut State, arguments: &[Node<Argument>]) -> fmt::Result {
757 if !arguments.is_empty() {
758 state.on_single_line(|state| {
759 comma_separated(state, "(", ")", arguments, |state, argument| {
760 argument.serialize_impl(state)
761 })
762 })?
763 }
764 Ok(())
765}
766
767fn comma_separated<T>(
777 state: &mut State,
778 open: &str,
779 close: &str,
780 values: &[T],
781 serialize_one: impl Fn(&mut State, &T) -> fmt::Result,
782) -> fmt::Result {
783 state.write(open)?;
784 if let Some((first, rest)) = values.split_first() {
785 state.indent()?;
786 serialize_one(state, first)?;
787 for value in rest {
788 state.write(",")?;
789 state.new_line_or_space()?;
790 serialize_one(state, value)?;
791 }
792 if state.newlines_enabled() {
794 state.write(",")?;
795 }
796 state.dedent()?;
797 }
798 state.write(close)
799}
800
801pub(crate) fn curly_brackets_space_separated<T>(
811 state: &mut State,
812 values: &[T],
813 serialize_one: impl Fn(&mut State, &T) -> fmt::Result,
814) -> fmt::Result {
815 state.write("{")?;
816 if let Some((first, rest)) = values.split_first() {
817 state.indent_or_space()?;
818 serialize_one(state, first)?;
819 for value in rest {
820 state.new_line_or_space()?;
821 serialize_one(state, value)?;
822 }
823 state.dedent_or_space()?;
824 }
825 state.write("}")
826}
827
828fn serialize_string_value(state: &mut State, is_description: bool, mut str: &str) -> fmt::Result {
829 let contains_newline = str.contains('\n');
830 let prefer_block_string = is_description || contains_newline;
831 if state.newlines_enabled() && prefer_block_string && can_be_block_string(str) {
832 return serialize_block_string(state, contains_newline, str);
833 }
834 state.write("\"")?;
835 loop {
836 if let Some(i) = str.find(|c| (c < ' ' && c != '\t') || c == '"' || c == '\\') {
837 let (without_escaping, rest) = str.split_at(i);
838 state.write(without_escaping)?;
839 match rest.as_bytes()[0] {
842 b'\x08' => state.write("\\b")?,
843 b'\n' => state.write("\\n")?,
844 b'\x0C' => state.write("\\f")?,
845 b'\r' => state.write("\\r")?,
846 b'"' => state.write("\\\"")?,
847 b'\\' => state.write("\\\\")?,
848 byte => display!(state, "\\u{:04X}", byte)?,
849 }
850 str = &rest[1..]
851 } else {
852 state.write(str)?;
853 break;
854 }
855 }
856 state.write("\"")
857}
858
859fn serialize_block_string(state: &mut State, contains_newline: bool, str: &str) -> fmt::Result {
860 const TRIPLE_QUOTE: &str = "\"\"\"";
861 const ESCAPED_TRIPLE_QUOTE: &str = "\\\"\"\"";
862 const _: () = assert!(TRIPLE_QUOTE.len() == 3);
863 const _: () = assert!(ESCAPED_TRIPLE_QUOTE.len() == 4);
864
865 fn serialize_line(state: &mut State, mut line: &str) -> Result<(), fmt::Error> {
866 while let Some((before, after)) = line.split_once(TRIPLE_QUOTE) {
867 state.write(before)?;
868 state.write(ESCAPED_TRIPLE_QUOTE)?;
869 line = after;
870 }
871 state.write(line)
872 }
873
874 let multi_line =
875 contains_newline || str.len() > 70 || str.ends_with('"') || str.ends_with('\\');
876
877 state.write(TRIPLE_QUOTE)?;
878 if !multi_line {
879 serialize_line(state, str)?
881 } else {
882 for line in str.split('\n') {
888 if line.is_empty() {
889 state.write("\n")?;
891 } else {
892 state.require_new_line()?;
893 serialize_line(state, line)?;
894 }
895 }
896 state.require_new_line()?;
897 }
898 state.write(TRIPLE_QUOTE)
899}
900
901fn can_be_block_string(value: &str) -> bool {
905 if value.contains('\r') {
908 return false;
909 }
910
911 fn trim_start_graphql_whitespace(value: &str) -> &str {
913 value.trim_start_matches([' ', '\t'])
914 }
915
916 let mut lines = value.split('\n');
918 if lines
919 .next()
920 .is_some_and(|first| trim_start_graphql_whitespace(first).is_empty())
921 || lines
922 .next_back()
923 .is_some_and(|last| trim_start_graphql_whitespace(last).is_empty())
924 {
925 return false;
927 }
928
929 let common_indent = {
930 let lines = value.split('\n');
931 let each_line_indent_utf8_len = lines.filter_map(|line| {
932 let after_indent = trim_start_graphql_whitespace(line);
933 if !after_indent.is_empty() {
934 Some(line.len() - after_indent.len())
935 } else {
936 None }
938 });
939 each_line_indent_utf8_len.min().unwrap_or(0)
940 };
941 common_indent == 0
944}
945
946fn serialize_description(state: &mut State, description: &Option<Node<str>>) -> fmt::Result {
947 if let Some(description) = description {
948 let is_description = true;
949 serialize_string_value(state, is_description, description)?;
950 state.new_line_or_space()?;
951 }
952 Ok(())
953}
954
955impl fmt::Display for Type {
956 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
957 match self {
958 Type::Named(name) => std::write!(f, "{name}"),
959 Type::NonNullNamed(name) => std::write!(f, "{name}!"),
960 Type::List(inner) => std::write!(f, "[{inner}]"),
961 Type::NonNullList(inner) => std::write!(f, "[{inner}]!"),
962 }
963 }
964}
965
966impl fmt::Display for OperationType {
967 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
968 self.name().fmt(f)
969 }
970}
971
972impl fmt::Display for DirectiveLocation {
973 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
974 self.name().fmt(f)
975 }
976}
977
978macro_rules! impl_display {
979 ($($ty: path)+) => {
980 $(
981 impl Display for $ty {
983 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
984 self.serialize().fmt(f)
985 }
986 }
987
988 impl Display for Serialize<'_, $ty> {
990 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
991 let mut state = State {
992 config: self.config.clone(),
993 indent_level: self.config.initial_indent_level,
994 output: f,
995 output_empty: true,
996 };
997 if let Some(prefix) = state.config.indent_prefix {
1000 for _ in 0..state.indent_level {
1001 state.write(prefix)?;
1002 }
1003 }
1004 self.node.serialize_impl(&mut state)
1005 }
1006 }
1007 )+
1008 }
1009}
1010
1011impl_display! {
1012 Document
1013 Definition
1014 OperationDefinition
1015 FragmentDefinition
1016 DirectiveDefinition
1017 SchemaDefinition
1018 ScalarTypeDefinition
1019 ObjectTypeDefinition
1020 InterfaceTypeDefinition
1021 UnionTypeDefinition
1022 EnumTypeDefinition
1023 InputObjectTypeDefinition
1024 SchemaExtension
1025 ScalarTypeExtension
1026 ObjectTypeExtension
1027 InterfaceTypeExtension
1028 UnionTypeExtension
1029 EnumTypeExtension
1030 InputObjectTypeExtension
1031 DirectiveList
1032 Directive
1033 VariableDefinition
1034 FieldDefinition
1035 InputValueDefinition
1036 EnumValueDefinition
1037 Selection
1038 Field
1039 FragmentSpread
1040 InlineFragment
1041 Value
1042 crate::Schema
1043 crate::ExecutableDocument
1044 schema::DirectiveList
1045 schema::ExtendedType
1046 schema::ScalarType
1047 schema::ObjectType
1048 schema::InterfaceType
1049 schema::EnumType
1050 schema::UnionType
1051 schema::InputObjectType
1052 executable::Operation
1053 executable::Fragment
1054 executable::SelectionSet
1055 executable::Selection
1056 executable::Field
1057 executable::InlineFragment
1058 executable::FragmentSpread
1059 executable::FieldSet
1060}