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::DirectiveExtension(def) => def.serialize_impl(state),
184 Definition::ScalarTypeExtension(def) => def.serialize_impl(state),
185 Definition::ObjectTypeExtension(def) => def.serialize_impl(state),
186 Definition::InterfaceTypeExtension(def) => def.serialize_impl(state),
187 Definition::UnionTypeExtension(def) => def.serialize_impl(state),
188 Definition::EnumTypeExtension(def) => def.serialize_impl(state),
189 Definition::InputObjectTypeExtension(def) => def.serialize_impl(state),
190 }
191 }
192}
193
194impl OperationDefinition {
195 fn serialize_impl(&self, state: &mut State) -> fmt::Result {
196 let Self {
198 operation_type,
199 name,
200 variables,
201 directives,
202 selection_set,
203 } = self;
204 let shorthand = state.output_empty
207 && *operation_type == OperationType::Query
208 && name.is_none()
209 && variables.is_empty()
210 && directives.is_empty();
211 if !shorthand {
212 state.write(operation_type.name())?;
213 if let Some(name) = &name {
214 state.write(" ")?;
215 state.write(name)?;
216 }
217 if !variables.is_empty() {
218 state.on_single_line(|state| {
219 comma_separated(state, "(", ")", variables, |state, var| {
220 var.serialize_impl(state)
221 })
222 })?
223 }
224 directives.serialize_impl(state)?;
225 state.write(" ")?;
226 }
227 curly_brackets_space_separated(state, selection_set, |state, sel| sel.serialize_impl(state))
228 }
229}
230
231impl FragmentDefinition {
232 fn serialize_impl(&self, state: &mut State) -> fmt::Result {
233 let Self {
234 name,
235 type_condition,
236 directives,
237 selection_set,
238 } = self;
239 display!(state, "fragment {} on {}", name, type_condition)?;
240 directives.serialize_impl(state)?;
241 state.write(" ")?;
242 curly_brackets_space_separated(state, selection_set, |state, sel| sel.serialize_impl(state))
243 }
244}
245
246impl DirectiveDefinition {
247 fn serialize_impl(&self, state: &mut State) -> fmt::Result {
248 let Self {
249 description,
250 name,
251 arguments,
252 repeatable,
253 locations,
254 directives,
255 } = self;
256 serialize_description(state, description)?;
257 state.write("directive @")?;
258 state.write(name)?;
259 serialize_arguments_definition(state, arguments)?;
260 directives.serialize_impl(state)?;
261
262 if *repeatable {
263 state.write(" repeatable")?;
264 }
265 if let Some((first, rest)) = locations.split_first() {
266 state.write(" on ")?;
267 state.write(first.name())?;
268 for location in rest {
269 state.write(" | ")?;
270 state.write(location.name())?;
271 }
272 }
273 Ok(())
274 }
275}
276
277fn serialize_arguments_definition(
278 state: &mut State,
279 arguments: &[Node<InputValueDefinition>],
280) -> fmt::Result {
281 if !arguments.is_empty() {
282 let serialize_arguments = |state: &mut State| {
283 comma_separated(state, "(", ")", arguments, |state, arg| {
284 arg.serialize_impl(state)
285 })
286 };
287 if arguments
288 .iter()
289 .any(|arg| arg.description.is_some() || !arg.directives.is_empty())
290 {
291 serialize_arguments(state)?
292 } else {
293 state.on_single_line(serialize_arguments)?
294 }
295 }
296 Ok(())
297}
298
299impl SchemaDefinition {
300 fn serialize_impl(&self, state: &mut State) -> fmt::Result {
301 let Self {
302 description,
303 directives,
304 root_operations,
305 } = self;
306 serialize_description(state, description)?;
307 state.write("schema")?;
308 directives.serialize_impl(state)?;
309 state.write(" ")?;
310 curly_brackets_space_separated(state, root_operations, |state, op| {
311 let (operation_type, operation_name) = &**op;
312 display!(state, "{}: {}", operation_type, operation_name)
313 })
314 }
315}
316
317impl ScalarTypeDefinition {
318 fn serialize_impl(&self, state: &mut State) -> fmt::Result {
319 let Self {
320 description,
321 name,
322 directives,
323 } = self;
324 serialize_description(state, description)?;
325 state.write("scalar ")?;
326 state.write(name)?;
327 directives.serialize_impl(state)
328 }
329}
330
331impl ObjectTypeDefinition {
332 fn serialize_impl(&self, state: &mut State) -> fmt::Result {
333 let Self {
334 description,
335 name,
336 implements_interfaces,
337 directives,
338 fields,
339 } = self;
340 serialize_description(state, description)?;
341 state.write("type ")?;
342 serialize_object_type_like(state, name, implements_interfaces, directives, fields)
343 }
344}
345
346fn serialize_object_type_like(
347 state: &mut State,
348 name: &str,
349 implements_interfaces: &[Name],
350 directives: &DirectiveList,
351 fields: &[Node<FieldDefinition>],
352) -> Result<(), fmt::Error> {
353 state.write(name)?;
354 if let Some((first, rest)) = implements_interfaces.split_first() {
355 state.write(" implements ")?;
356 state.write(first)?;
357 for name in rest {
358 state.write(" & ")?;
359 state.write(name)?;
360 }
361 }
362 directives.serialize_impl(state)?;
363
364 if !fields.is_empty() {
365 state.write(" ")?;
366 curly_brackets_space_separated(state, fields, |state, field| field.serialize_impl(state))?;
367 }
368 Ok(())
369}
370
371impl InterfaceTypeDefinition {
372 fn serialize_impl(&self, state: &mut State) -> fmt::Result {
373 let Self {
374 description,
375 name,
376 implements_interfaces,
377 directives,
378 fields,
379 } = self;
380 serialize_description(state, description)?;
381 state.write("interface ")?;
382 serialize_object_type_like(state, name, implements_interfaces, directives, fields)
383 }
384}
385
386impl UnionTypeDefinition {
387 fn serialize_impl(&self, state: &mut State) -> fmt::Result {
388 let Self {
389 description,
390 name,
391 directives,
392 members,
393 } = self;
394 serialize_description(state, description)?;
395 state.write("union ")?;
396 serialize_union(state, name, directives, members)
397 }
398}
399
400fn serialize_union(
401 state: &mut State,
402 name: &str,
403 directives: &DirectiveList,
404 members: &[Name],
405) -> fmt::Result {
406 state.write(name)?;
407 directives.serialize_impl(state)?;
408 if let Some((first, rest)) = members.split_first() {
409 state.write(" = ")?;
410 state.write(first)?;
411 for member in rest {
412 state.write(" | ")?;
413 state.write(member)?;
414 }
415 }
416 Ok(())
417}
418
419impl EnumTypeDefinition {
420 fn serialize_impl(&self, state: &mut State) -> fmt::Result {
421 let Self {
422 description,
423 name,
424 directives,
425 values,
426 } = self;
427 serialize_description(state, description)?;
428 state.write("enum ")?;
429 state.write(name)?;
430 directives.serialize_impl(state)?;
431 if !values.is_empty() {
432 state.write(" ")?;
433 curly_brackets_space_separated(state, values, |state, value| {
434 value.serialize_impl(state)
435 })?;
436 }
437 Ok(())
438 }
439}
440
441impl InputObjectTypeDefinition {
442 fn serialize_impl(&self, state: &mut State) -> fmt::Result {
443 let Self {
444 description,
445 name,
446 directives,
447 fields,
448 } = self;
449 serialize_description(state, description)?;
450 state.write("input ")?;
451 state.write(name)?;
452 directives.serialize_impl(state)?;
453 if !fields.is_empty() {
454 state.write(" ")?;
455 curly_brackets_space_separated(state, fields, |state, f| f.serialize_impl(state))?;
456 }
457 Ok(())
458 }
459}
460
461impl SchemaExtension {
462 fn serialize_impl(&self, state: &mut State) -> fmt::Result {
463 let Self {
464 directives,
465 root_operations,
466 } = self;
467 state.write("extend schema")?;
468 directives.serialize_impl(state)?;
469 if !root_operations.is_empty() {
470 state.write(" ")?;
471 curly_brackets_space_separated(state, root_operations, |state, op| {
472 let (operation_type, operation_name) = &**op;
473 display!(state, "{}: {}", operation_type, operation_name)
474 })?;
475 }
476 Ok(())
477 }
478}
479
480impl DirectiveExtension {
481 fn serialize_impl(&self, state: &mut State) -> fmt::Result {
482 let Self { name, directives } = self;
483 state.write("extend directive @")?;
484 state.write(name)?;
485 directives.serialize_impl(state)
486 }
487}
488
489impl ScalarTypeExtension {
490 fn serialize_impl(&self, state: &mut State) -> fmt::Result {
491 let Self { name, directives } = self;
492 state.write("extend scalar ")?;
493 state.write(name)?;
494 directives.serialize_impl(state)
495 }
496}
497
498impl ObjectTypeExtension {
499 fn serialize_impl(&self, state: &mut State) -> fmt::Result {
500 let Self {
501 name,
502 implements_interfaces,
503 directives,
504 fields,
505 } = self;
506 state.write("extend type ")?;
507 serialize_object_type_like(state, name, implements_interfaces, directives, fields)
508 }
509}
510
511impl InterfaceTypeExtension {
512 fn serialize_impl(&self, state: &mut State) -> fmt::Result {
513 let Self {
514 name,
515 implements_interfaces,
516 directives,
517 fields,
518 } = self;
519 state.write("extend interface ")?;
520 serialize_object_type_like(state, name, implements_interfaces, directives, fields)
521 }
522}
523
524impl UnionTypeExtension {
525 fn serialize_impl(&self, state: &mut State) -> fmt::Result {
526 let Self {
527 name,
528 directives,
529 members,
530 } = self;
531 state.write("extend union ")?;
532 serialize_union(state, name, directives, members)
533 }
534}
535
536impl EnumTypeExtension {
537 fn serialize_impl(&self, state: &mut State) -> fmt::Result {
538 let Self {
539 name,
540 directives,
541 values,
542 } = self;
543 state.write("extend enum ")?;
544 state.write(name)?;
545 directives.serialize_impl(state)?;
546 if !values.is_empty() {
547 state.write(" ")?;
548 curly_brackets_space_separated(state, values, |state, value| {
549 value.serialize_impl(state)
550 })?;
551 }
552 Ok(())
553 }
554}
555
556impl InputObjectTypeExtension {
557 fn serialize_impl(&self, state: &mut State) -> fmt::Result {
558 let Self {
559 name,
560 directives,
561 fields,
562 } = self;
563 state.write("extend input ")?;
564 state.write(name)?;
565 directives.serialize_impl(state)?;
566 if !fields.is_empty() {
567 state.write(" ")?;
568 curly_brackets_space_separated(state, fields, |state, f| f.serialize_impl(state))?;
569 }
570 Ok(())
571 }
572}
573
574impl DirectiveList {
575 fn serialize_impl(&self, state: &mut State) -> fmt::Result {
576 for dir in self {
577 state.write(" ")?;
578 dir.serialize_impl(state)?;
579 }
580 Ok(())
581 }
582}
583
584impl Directive {
585 pub(crate) fn serialize_impl(&self, state: &mut State) -> fmt::Result {
586 let Self { name, arguments } = self;
587 state.write("@")?;
588 state.write(name)?;
589 serialize_arguments(state, arguments)
590 }
591}
592
593impl VariableDefinition {
594 fn serialize_impl(&self, state: &mut State) -> fmt::Result {
595 let Self {
596 name,
597 ty,
598 default_value,
599 directives,
600 } = self;
601 state.write("$")?;
602 state.write(name)?;
603 state.write(": ")?;
604 display!(state, ty)?;
605 if let Some(value) = default_value {
606 state.write(" = ")?;
607 value.serialize_impl(state)?
608 }
609 directives.serialize_impl(state)
610 }
611}
612
613impl FieldDefinition {
614 fn serialize_impl(&self, state: &mut State) -> fmt::Result {
615 let Self {
616 description,
617 name,
618 arguments,
619 ty,
620 directives,
621 } = self;
622 serialize_description(state, description)?;
623 state.write(name)?;
624 serialize_arguments_definition(state, arguments)?;
625 state.write(": ")?;
626 display!(state, ty)?;
627 directives.serialize_impl(state)
628 }
629}
630
631impl InputValueDefinition {
632 fn serialize_impl(&self, state: &mut State) -> fmt::Result {
633 let Self {
634 description,
635 name,
636 ty,
637 default_value,
638 directives,
639 } = self;
640 serialize_description(state, description)?;
641 state.write(name)?;
642 state.write(": ")?;
643 display!(state, ty)?;
644 if let Some(value) = default_value {
645 state.write(" = ")?;
646 value.serialize_impl(state)?
647 }
648 directives.serialize_impl(state)
649 }
650}
651
652impl EnumValueDefinition {
653 fn serialize_impl(&self, state: &mut State) -> fmt::Result {
654 let Self {
655 description,
656 value,
657 directives,
658 } = self;
659 serialize_description(state, description)?;
660 state.write(value)?;
661 directives.serialize_impl(state)
662 }
663}
664
665impl Selection {
666 pub(crate) fn serialize_impl(&self, state: &mut State) -> fmt::Result {
667 match self {
668 Selection::Field(x) => x.serialize_impl(state),
669 Selection::FragmentSpread(x) => x.serialize_impl(state),
670 Selection::InlineFragment(x) => x.serialize_impl(state),
671 }
672 }
673}
674
675impl Field {
676 pub(crate) fn serialize_impl(&self, state: &mut State) -> fmt::Result {
677 let Self {
678 alias,
679 name,
680 arguments,
681 directives,
682 selection_set_is_explicit,
683 selection_set,
684 } = self;
685 if let Some(alias) = alias {
686 state.write(alias)?;
687 state.write(": ")?;
688 }
689 state.write(name)?;
690 serialize_arguments(state, arguments)?;
691 directives.serialize_impl(state)?;
692 if *selection_set_is_explicit {
693 state.write(" ")?;
694 curly_brackets_space_separated(state, selection_set, |state, sel| {
695 sel.serialize_impl(state)
696 })?
697 }
698 Ok(())
699 }
700}
701
702impl FragmentSpread {
703 pub(crate) fn serialize_impl(&self, state: &mut State) -> fmt::Result {
704 let Self {
705 fragment_name,
706 directives,
707 } = self;
708 state.write("...")?;
709 state.write(fragment_name)?;
710 directives.serialize_impl(state)
711 }
712}
713
714impl InlineFragment {
715 pub(crate) fn serialize_impl(&self, state: &mut State) -> fmt::Result {
716 let Self {
717 type_condition,
718 directives,
719 selection_set,
720 } = self;
721 if let Some(type_name) = type_condition {
722 state.write("... on ")?;
723 state.write(type_name)?;
724 } else {
725 state.write("...")?;
726 }
727 directives.serialize_impl(state)?;
728 state.write(" ")?;
729 curly_brackets_space_separated(state, selection_set, |state, sel| sel.serialize_impl(state))
730 }
731}
732
733impl Value {
734 fn serialize_impl(&self, state: &mut State) -> fmt::Result {
735 match self {
736 Value::Null => state.write("null"),
737 Value::Boolean(true) => state.write("true"),
738 Value::Boolean(false) => state.write("false"),
739 Value::Enum(name) => state.write(name),
740 Value::String(value) => {
741 let is_description = false;
742 serialize_string_value(state, is_description, value)
743 }
744 Value::Variable(name) => display!(state, "${}", name),
745 Value::Float(value) => display!(state, value),
746 Value::Int(value) => display!(state, value),
747 Value::List(value) => comma_separated(state, "[", "]", value, |state, value| {
748 value.serialize_impl(state)
749 }),
750 Value::Object(value) => {
751 comma_separated(state, "{", "}", value, |state, (name, value)| {
752 state.write(name)?;
753 state.write(": ")?;
754 value.serialize_impl(state)
755 })
756 }
757 }
758 }
759}
760
761impl Argument {
762 fn serialize_impl(&self, state: &mut State) -> fmt::Result {
763 state.write(&self.name)?;
764 state.write(": ")?;
765 self.value.serialize_impl(state)
766 }
767}
768
769fn serialize_arguments(state: &mut State, arguments: &[Node<Argument>]) -> fmt::Result {
770 if !arguments.is_empty() {
771 state.on_single_line(|state| {
772 comma_separated(state, "(", ")", arguments, |state, argument| {
773 argument.serialize_impl(state)
774 })
775 })?
776 }
777 Ok(())
778}
779
780fn comma_separated<T>(
790 state: &mut State,
791 open: &str,
792 close: &str,
793 values: &[T],
794 serialize_one: impl Fn(&mut State, &T) -> fmt::Result,
795) -> fmt::Result {
796 state.write(open)?;
797 if let Some((first, rest)) = values.split_first() {
798 state.indent()?;
799 serialize_one(state, first)?;
800 for value in rest {
801 state.write(",")?;
802 state.new_line_or_space()?;
803 serialize_one(state, value)?;
804 }
805 if state.newlines_enabled() {
807 state.write(",")?;
808 }
809 state.dedent()?;
810 }
811 state.write(close)
812}
813
814pub(crate) fn curly_brackets_space_separated<T>(
824 state: &mut State,
825 values: &[T],
826 serialize_one: impl Fn(&mut State, &T) -> fmt::Result,
827) -> fmt::Result {
828 state.write("{")?;
829 if let Some((first, rest)) = values.split_first() {
830 state.indent_or_space()?;
831 serialize_one(state, first)?;
832 for value in rest {
833 state.new_line_or_space()?;
834 serialize_one(state, value)?;
835 }
836 state.dedent_or_space()?;
837 }
838 state.write("}")
839}
840
841fn serialize_string_value(state: &mut State, is_description: bool, mut str: &str) -> fmt::Result {
842 let contains_newline = str.contains('\n');
843 let prefer_block_string = is_description || contains_newline;
844 if state.newlines_enabled() && prefer_block_string && can_be_block_string(str) {
845 return serialize_block_string(state, contains_newline, str);
846 }
847 state.write("\"")?;
848 loop {
849 if let Some(i) = str.find(|c| (c < ' ' && c != '\t') || c == '"' || c == '\\') {
850 let (without_escaping, rest) = str.split_at(i);
851 state.write(without_escaping)?;
852 match rest.as_bytes()[0] {
855 b'\x08' => state.write("\\b")?,
856 b'\n' => state.write("\\n")?,
857 b'\x0C' => state.write("\\f")?,
858 b'\r' => state.write("\\r")?,
859 b'"' => state.write("\\\"")?,
860 b'\\' => state.write("\\\\")?,
861 byte => display!(state, "\\u{:04X}", byte)?,
862 }
863 str = &rest[1..]
864 } else {
865 state.write(str)?;
866 break;
867 }
868 }
869 state.write("\"")
870}
871
872fn serialize_block_string(state: &mut State, contains_newline: bool, str: &str) -> fmt::Result {
873 const TRIPLE_QUOTE: &str = "\"\"\"";
874 const ESCAPED_TRIPLE_QUOTE: &str = "\\\"\"\"";
875 const _: () = assert!(TRIPLE_QUOTE.len() == 3);
876 const _: () = assert!(ESCAPED_TRIPLE_QUOTE.len() == 4);
877
878 fn serialize_line(state: &mut State, mut line: &str) -> Result<(), fmt::Error> {
879 while let Some((before, after)) = line.split_once(TRIPLE_QUOTE) {
880 state.write(before)?;
881 state.write(ESCAPED_TRIPLE_QUOTE)?;
882 line = after;
883 }
884 state.write(line)
885 }
886
887 let multi_line =
888 contains_newline || str.len() > 70 || str.ends_with('"') || str.ends_with('\\');
889
890 state.write(TRIPLE_QUOTE)?;
891 if !multi_line {
892 serialize_line(state, str)?
894 } else {
895 for line in str.split('\n') {
901 if line.is_empty() {
902 state.write("\n")?;
904 } else {
905 state.require_new_line()?;
906 serialize_line(state, line)?;
907 }
908 }
909 state.require_new_line()?;
910 }
911 state.write(TRIPLE_QUOTE)
912}
913
914fn can_be_block_string(value: &str) -> bool {
918 if value.contains('\r') {
921 return false;
922 }
923
924 fn trim_start_graphql_whitespace(value: &str) -> &str {
926 value.trim_start_matches([' ', '\t'])
927 }
928
929 let mut lines = value.split('\n');
931 if lines
932 .next()
933 .is_some_and(|first| trim_start_graphql_whitespace(first).is_empty())
934 || lines
935 .next_back()
936 .is_some_and(|last| trim_start_graphql_whitespace(last).is_empty())
937 {
938 return false;
940 }
941
942 let common_indent = {
943 let lines = value.split('\n');
944 let each_line_indent_utf8_len = lines.filter_map(|line| {
945 let after_indent = trim_start_graphql_whitespace(line);
946 if !after_indent.is_empty() {
947 Some(line.len() - after_indent.len())
948 } else {
949 None }
951 });
952 each_line_indent_utf8_len.min().unwrap_or(0)
953 };
954 common_indent == 0
957}
958
959fn serialize_description(state: &mut State, description: &Option<Node<str>>) -> fmt::Result {
960 if let Some(description) = description {
961 let is_description = true;
962 serialize_string_value(state, is_description, description)?;
963 state.new_line_or_space()?;
964 }
965 Ok(())
966}
967
968impl fmt::Display for Type {
969 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
970 match self {
971 Type::Named(name) => std::write!(f, "{name}"),
972 Type::NonNullNamed(name) => std::write!(f, "{name}!"),
973 Type::List(inner) => std::write!(f, "[{inner}]"),
974 Type::NonNullList(inner) => std::write!(f, "[{inner}]!"),
975 }
976 }
977}
978
979impl fmt::Display for OperationType {
980 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
981 self.name().fmt(f)
982 }
983}
984
985impl fmt::Display for DirectiveLocation {
986 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
987 self.name().fmt(f)
988 }
989}
990
991macro_rules! impl_display {
992 ($($ty: path)+) => {
993 $(
994 impl Display for $ty {
996 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
997 self.serialize().fmt(f)
998 }
999 }
1000
1001 impl Display for Serialize<'_, $ty> {
1003 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1004 let mut state = State {
1005 config: self.config.clone(),
1006 indent_level: self.config.initial_indent_level,
1007 output: f,
1008 output_empty: true,
1009 };
1010 if let Some(prefix) = state.config.indent_prefix {
1013 for _ in 0..state.indent_level {
1014 state.write(prefix)?;
1015 }
1016 }
1017 self.node.serialize_impl(&mut state)
1018 }
1019 }
1020 )+
1021 }
1022}
1023
1024impl_display! {
1025 Document
1026 Definition
1027 OperationDefinition
1028 FragmentDefinition
1029 DirectiveDefinition
1030 SchemaDefinition
1031 ScalarTypeDefinition
1032 ObjectTypeDefinition
1033 InterfaceTypeDefinition
1034 UnionTypeDefinition
1035 EnumTypeDefinition
1036 InputObjectTypeDefinition
1037 SchemaExtension
1038 DirectiveExtension
1039 ScalarTypeExtension
1040 ObjectTypeExtension
1041 InterfaceTypeExtension
1042 UnionTypeExtension
1043 EnumTypeExtension
1044 InputObjectTypeExtension
1045 DirectiveList
1046 Directive
1047 VariableDefinition
1048 FieldDefinition
1049 InputValueDefinition
1050 EnumValueDefinition
1051 Selection
1052 Field
1053 FragmentSpread
1054 InlineFragment
1055 Value
1056 crate::Schema
1057 crate::ExecutableDocument
1058 schema::DirectiveList
1059 schema::ExtendedType
1060 schema::ScalarType
1061 schema::ObjectType
1062 schema::InterfaceType
1063 schema::EnumType
1064 schema::UnionType
1065 schema::InputObjectType
1066 executable::Operation
1067 executable::Fragment
1068 executable::SelectionSet
1069 executable::Selection
1070 executable::Field
1071 executable::InlineFragment
1072 executable::FragmentSpread
1073 executable::FieldSet
1074}