graphql_toolkit_writer/
ser.rs

1use std::io;
2
3use graphql_toolkit_ast::{
4    indexmap::IndexMap, BaseType, ConstValue, Directive, DocumentOperations, ExecutableDocument,
5    Field, FragmentDefinition, FragmentSpread, InlineFragment, Name, Number, OperationDefinition,
6    OperationType, Positioned, Selection, SelectionSet, Type, TypeCondition, Value,
7    VariableDefinition,
8};
9
10use crate::fmt::formatter::Formatter;
11
12/// A trait for serializing a GraphQL AST into a GraphQL document.
13pub trait Serialize {
14    /// Serialize this value into the given serializer.
15    fn serialize<W, F>(&self, ser: &mut Serializer<W, F>) -> anyhow::Result<()>
16    where
17        W: io::Write,
18        F: Formatter;
19}
20
21/// A structure for serializing Rust GraphQL AST types to GraphQL documents.
22pub struct Serializer<W, F> {
23    writer: W,
24    formatter: F,
25}
26
27impl<W, F> Serializer<W, F>
28where
29    W: io::Write,
30    F: Formatter,
31{
32    /// Create a new serializer with a custom formatter.
33    #[inline]
34    pub fn with_formatter(writer: W, formatter: F) -> Self {
35        Self { writer, formatter }
36    }
37}
38
39impl<W, F> Serializer<W, F>
40where
41    W: io::Write,
42    F: Formatter,
43{
44    fn serialize_executable_document(&mut self, value: &ExecutableDocument) -> anyhow::Result<()> {
45        match &value.operations {
46            DocumentOperations::Single(def) => {
47                self.serialize_operation_definition(&def.node, None, true)?;
48            }
49            DocumentOperations::Multiple(def) => {
50                let mut first_operation = true;
51                for (name, def) in def.iter() {
52                    if !first_operation {
53                        self.formatter
54                            .before_operation_or_fragment_definition(&mut self.writer)?;
55                    }
56
57                    self.serialize_operation_definition(&def.node, Some(name), false)?;
58                    first_operation = false;
59                }
60            }
61        }
62
63        for (name, fragment) in value.fragments.iter() {
64            self.formatter
65                .before_operation_or_fragment_definition(&mut self.writer)?;
66            self.serialize_fragment_definition(name, &fragment.node)?;
67        }
68
69        Ok(())
70    }
71
72    fn serialize_operation_definition(
73        &mut self,
74        value: &OperationDefinition,
75        name: Option<&Name>,
76        single: bool,
77    ) -> anyhow::Result<()> {
78        // Use the "query shorthand" if a document contains *only one operation* and
79        // that operation is a query which defines *no variables* and contains *no
80        // directives* then that operation may be represented in a shorthand form
81        // which omits the query keyword and operation name. For example:
82        //
83        //  { field }
84        //
85        // https://spec.graphql.org/October2021/#sec-Language.Operations.Query-shorthand
86        let shorthand = single
87            && value.ty == OperationType::Query
88            && name.is_none()
89            && value.variable_definitions.is_empty()
90            && value.directives.is_empty();
91
92        // Operation signature
93        if !shorthand {
94            // Type
95            match value.ty {
96                OperationType::Query => {
97                    self.formatter.write_keyword(&mut self.writer, "query")?;
98                }
99                OperationType::Mutation => {
100                    self.formatter.write_keyword(&mut self.writer, "mutation")?;
101                }
102                OperationType::Subscription => {
103                    self.formatter
104                        .write_keyword(&mut self.writer, "subscription")?;
105                }
106            }
107
108            // Name
109            if let Some(name) = name {
110                self.formatter.write_separator(&mut self.writer)?;
111                name.serialize(self)?;
112            }
113
114            // Variables definition
115            if name.is_none() && !value.variable_definitions.is_empty() {
116                self.formatter
117                    .before_operation_variable_definitions(&mut self.writer)?;
118            }
119            if !value.variable_definitions.is_empty() {
120                self.formatter.begin_parentheses(&mut self.writer)?;
121
122                let mut iter = value.variable_definitions.iter().peekable();
123                while let Some(def) = iter.next() {
124                    def.serialize(self)?;
125
126                    // If there are more variable definitions, add a separator
127                    if iter.peek().is_some() {
128                        self.formatter.write_item_separator(&mut self.writer)?;
129                    }
130                }
131
132                self.formatter.end_parentheses(&mut self.writer)?;
133            }
134
135            // Directives
136            for directive in value.directives.iter() {
137                directive.serialize(self)?;
138            }
139
140            self.formatter
141                .after_operation_or_fragment_signature(&mut self.writer)?;
142        }
143
144        // Selection set
145        value.selection_set.serialize(self)?;
146
147        Ok(())
148    }
149
150    fn serialize_selection_set(&mut self, value: &SelectionSet) -> anyhow::Result<()> {
151        // Empty selection sets are not serialized
152        if value.items.is_empty() {
153            return Ok(());
154        }
155
156        self.formatter.begin_block(&mut self.writer)?;
157
158        let mut iter = value.items.iter().peekable();
159        while let Some(selection) = iter.next() {
160            self.formatter.before_block_item(&mut self.writer)?;
161            selection.serialize(self)?;
162
163            // If there are more selections, add a separator
164            if iter.peek().is_some() {
165                self.formatter.after_block_item(&mut self.writer)?;
166            }
167        }
168
169        self.formatter.end_block(&mut self.writer)?;
170
171        Ok(())
172    }
173
174    fn serialize_selection(&mut self, value: &Selection) -> anyhow::Result<()> {
175        match value {
176            Selection::Field(field) => field.serialize(self),
177            Selection::FragmentSpread(fragment) => fragment.serialize(self),
178            Selection::InlineFragment(fragment) => fragment.serialize(self),
179        }?;
180
181        Ok(())
182    }
183
184    fn serialize_selection_field(&mut self, value: &Field) -> anyhow::Result<()> {
185        if let Some(alias) = &value.alias {
186            alias.serialize(self)?;
187            self.formatter
188                .write_name_value_separator(&mut self.writer)?;
189        }
190
191        value.name.serialize(self)?;
192
193        if !value.arguments.is_empty() {
194            self.serialize_arguments(&value.arguments)?;
195        }
196
197        for directive in value.directives.iter() {
198            directive.serialize(self)?;
199        }
200
201        if !value.selection_set.node.items.is_empty() {
202            self.formatter.after_selection_signature(&mut self.writer)?;
203        }
204        value.selection_set.serialize(self)?;
205
206        Ok(())
207    }
208
209    fn serialize_fragment_spread(&mut self, value: &FragmentSpread) -> anyhow::Result<()> {
210        self.formatter.write_keyword(&mut self.writer, "...")?;
211        value.fragment_name.serialize(self)?;
212
213        for directive in value.directives.iter() {
214            directive.serialize(self)?;
215        }
216
217        Ok(())
218    }
219
220    fn serialize_inline_fragment(&mut self, value: &InlineFragment) -> anyhow::Result<()> {
221        self.formatter.write_keyword(&mut self.writer, "...")?;
222
223        if let Some(type_condition) = &value.type_condition {
224            self.formatter.before_type_condition(&mut self.writer)?;
225            type_condition.serialize(self)?;
226        }
227
228        for directive in value.directives.iter() {
229            directive.serialize(self)?;
230        }
231
232        if !value.selection_set.node.items.is_empty() {
233            self.formatter.after_selection_signature(&mut self.writer)?;
234        }
235        value.selection_set.serialize(self)?;
236
237        Ok(())
238    }
239
240    fn serialize_arguments(
241        &mut self,
242        value: &[(Positioned<Name>, Positioned<Value>)],
243    ) -> anyhow::Result<()> {
244        self.formatter.begin_parentheses(&mut self.writer)?;
245
246        let mut iter = value.iter().peekable();
247        while let Some((name, value)) = iter.next() {
248            name.serialize(self)?;
249            self.formatter
250                .write_name_value_separator(&mut self.writer)?;
251            value.serialize(self)?;
252
253            // If there are more arguments, add a separator
254            if iter.peek().is_some() {
255                self.formatter.write_item_separator(&mut self.writer)?;
256            }
257        }
258
259        self.formatter.end_parentheses(&mut self.writer)?;
260
261        Ok(())
262    }
263
264    fn serialize_directive(&mut self, value: &Directive) -> anyhow::Result<()> {
265        self.formatter.before_directive(&mut self.writer)?;
266
267        // Directive name
268        self.formatter.begin_directive(&mut self.writer)?;
269        value.name.serialize(self)?;
270
271        // Arguments
272        if !value.arguments.is_empty() {
273            self.serialize_arguments(&value.arguments)?;
274        }
275
276        Ok(())
277    }
278
279    fn serialize_variable_definition(&mut self, value: &VariableDefinition) -> anyhow::Result<()> {
280        // Variable name
281        self.formatter.begin_variable(&mut self.writer)?;
282        value.name.serialize(self)?;
283
284        // Variable name-type separator
285        self.formatter
286            .write_name_value_separator(&mut self.writer)?;
287
288        // Variable type
289        value.var_type.serialize(self)?;
290
291        if let Some(default_value) = &value.default_value {
292            self.formatter
293                .write_variable_default_value_separator(&mut self.writer)?;
294            default_value.serialize(self)?;
295        }
296
297        for directive in value.directives.iter() {
298            directive.serialize(self)?;
299        }
300
301        Ok(())
302    }
303
304    fn serialize_type(&mut self, value: &Type) -> anyhow::Result<()> {
305        match &value.base {
306            BaseType::Named(name) => {
307                name.serialize(self)?;
308            }
309            BaseType::List(list) => {
310                self.formatter.begin_array(&mut self.writer)?;
311                list.serialize(self)?;
312                self.formatter.end_array(&mut self.writer)?;
313            }
314        }
315
316        if !value.nullable {
317            self.formatter
318                .write_non_null_type_indicator(&mut self.writer)?;
319        }
320
321        Ok(())
322    }
323
324    fn serialize_fragment_definition(
325        &mut self,
326        name: &Name,
327        value: &FragmentDefinition,
328    ) -> anyhow::Result<()> {
329        self.formatter.write_keyword(&mut self.writer, "fragment")?;
330
331        self.formatter.write_separator(&mut self.writer)?;
332        name.serialize(self)?;
333        self.formatter.write_separator(&mut self.writer)?;
334
335        value.type_condition.serialize(self)?;
336
337        for directive in value.directives.iter() {
338            directive.serialize(self)?;
339        }
340
341        self.formatter
342            .after_operation_or_fragment_signature(&mut self.writer)?;
343
344        value.selection_set.serialize(self)?;
345
346        Ok(())
347    }
348
349    fn serialize_type_condition(&mut self, value: &TypeCondition) -> anyhow::Result<()> {
350        self.formatter.write_keyword(&mut self.writer, "on")?;
351        self.formatter.write_separator(&mut self.writer)?;
352        value.on.serialize(self)
353    }
354
355    fn serialize_name(&mut self, value: &Name) -> anyhow::Result<()> {
356        self.formatter
357            .write_string_fragment(&mut self.writer, value)?;
358
359        Ok(())
360    }
361
362    fn serialize_value(&mut self, value: &Value) -> anyhow::Result<()> {
363        match value {
364            Value::Null => {
365                self.formatter.write_null(&mut self.writer)?;
366            }
367            Value::Number(value) => {
368                value.serialize(self)?;
369            }
370            // TODO: Support string character escaping
371            Value::String(value) => {
372                self.formatter.begin_string(&mut self.writer)?;
373                self.formatter
374                    .write_string_fragment(&mut self.writer, value)?;
375                self.formatter.end_string(&mut self.writer)?;
376            }
377            Value::Boolean(value) => {
378                self.formatter.write_bool(&mut self.writer, *value)?;
379            }
380            Value::Variable(name) => {
381                self.formatter.begin_variable(&mut self.writer)?;
382                name.serialize(self)?;
383            }
384            Value::Enum(value) => {
385                value.serialize(self)?;
386            }
387            Value::List(list) => {
388                self.serialize_value_array(list)?;
389            }
390            Value::Object(value) => {
391                self.serialize_value_object(value)?;
392            }
393            Value::Binary(value) => {
394                self.formatter
395                    .write_byte_array(&mut self.writer, &value[..])?;
396            }
397        }
398
399        Ok(())
400    }
401
402    fn serialize_value_array(&mut self, value: &[Value]) -> anyhow::Result<()> {
403        self.formatter.begin_array(&mut self.writer)?;
404
405        let mut iter = value.iter().peekable();
406        while let Some(value) = iter.next() {
407            value.serialize(self)?;
408
409            // If there are more items, add a separator
410            if iter.peek().is_some() {
411                self.formatter.write_item_separator(&mut self.writer)?;
412            }
413        }
414
415        self.formatter.end_array(&mut self.writer)?;
416
417        Ok(())
418    }
419
420    fn serialize_value_object(&mut self, value: &IndexMap<Name, Value>) -> anyhow::Result<()> {
421        self.formatter.begin_object(&mut self.writer)?;
422
423        let mut iter = value.iter().peekable();
424        while let Some((key, value)) = iter.next() {
425            key.serialize(self)?;
426            self.formatter
427                .write_name_value_separator(&mut self.writer)?;
428            value.serialize(self)?;
429
430            // If there are more items, add a separator
431            if iter.peek().is_some() {
432                self.formatter.write_item_separator(&mut self.writer)?;
433            }
434        }
435
436        self.formatter.end_object(&mut self.writer)?;
437
438        Ok(())
439    }
440
441    fn serialize_const_value(&mut self, value: &ConstValue) -> anyhow::Result<()> {
442        match value {
443            ConstValue::Null => {
444                self.formatter.write_null(&mut self.writer)?;
445            }
446            ConstValue::Number(value) => {
447                value.serialize(self)?;
448            }
449            ConstValue::String(value) => {
450                // TODO: Support string character escaping
451                self.formatter.begin_string(&mut self.writer)?;
452                self.formatter
453                    .write_string_fragment(&mut self.writer, value)?;
454                self.formatter.end_string(&mut self.writer)?;
455            }
456            ConstValue::Boolean(value) => {
457                self.formatter.write_bool(&mut self.writer, *value)?;
458            }
459            ConstValue::Enum(value) => {
460                value.serialize(self)?;
461            }
462            ConstValue::List(list) => {
463                self.serialize_const_value_array(list)?;
464            }
465            ConstValue::Object(object) => {
466                self.serialize_const_value_object(object)?;
467            }
468            ConstValue::Binary(value) => {
469                self.formatter
470                    .write_byte_array(&mut self.writer, &value[..])?;
471            }
472        }
473
474        Ok(())
475    }
476
477    fn serialize_const_value_array(&mut self, value: &[ConstValue]) -> anyhow::Result<()> {
478        self.formatter.begin_array(&mut self.writer)?;
479
480        let mut iter = value.iter().peekable();
481        while let Some(value) = iter.next() {
482            value.serialize(self)?;
483
484            // If there are more items, add a separator
485            if iter.peek().is_some() {
486                self.formatter.write_item_separator(&mut self.writer)?;
487            }
488        }
489
490        self.formatter.end_array(&mut self.writer)?;
491
492        Ok(())
493    }
494
495    fn serialize_const_value_object(
496        &mut self,
497        value: &IndexMap<Name, ConstValue>,
498    ) -> anyhow::Result<()> {
499        self.formatter.begin_object(&mut self.writer)?;
500
501        let mut iter = value.iter().peekable();
502        while let Some((key, value)) = iter.next() {
503            key.serialize(self)?;
504            self.formatter
505                .write_name_value_separator(&mut self.writer)?;
506            value.serialize(self)?;
507
508            // If there are more items, add a separator
509            if iter.peek().is_some() {
510                self.formatter.write_item_separator(&mut self.writer)?;
511            }
512        }
513
514        self.formatter.end_object(&mut self.writer)?;
515
516        Ok(())
517    }
518
519    fn serialize_number(&mut self, value: &Number) -> anyhow::Result<()> {
520        if let Some(u) = value.as_u64() {
521            self.formatter.write_u64(&mut self.writer, u)?;
522        } else if let Some(i) = value.as_i64() {
523            self.formatter.write_i64(&mut self.writer, i)?;
524        } else if let Some(f) = value.as_f64() {
525            self.formatter.write_f64(&mut self.writer, f)?;
526        } else {
527            unreachable!("invalid number")
528        }
529
530        Ok(())
531    }
532}
533
534// Implement `AstSerialize` for a type that can be serialized.
535macro_rules! impl_serialize {
536    ($ty:ty, $method:ident) => {
537        impl Serialize for $ty {
538            #[inline]
539            fn serialize<W, F>(&self, ser: &mut Serializer<W, F>) -> anyhow::Result<()>
540            where
541                W: io::Write,
542                F: Formatter,
543            {
544                ser.$method(self)
545            }
546        }
547    };
548}
549
550impl<T> Serialize for Positioned<T>
551where
552    T: Serialize,
553{
554    #[inline]
555    fn serialize<W, F>(&self, ser: &mut Serializer<W, F>) -> anyhow::Result<()>
556    where
557        W: io::Write,
558        F: Formatter,
559    {
560        self.node.serialize(ser)
561    }
562}
563
564impl Serialize for OperationDefinition {
565    #[inline]
566    fn serialize<W, F>(&self, ser: &mut Serializer<W, F>) -> anyhow::Result<()>
567    where
568        W: io::Write,
569        F: Formatter,
570    {
571        // If we are serializing an "operation definition" instance assume that there is a single
572        // operation in the document
573        ser.serialize_operation_definition(self, None, true)
574    }
575}
576
577impl Serialize for (Name, OperationDefinition) {
578    #[inline]
579    fn serialize<W, F>(&self, ser: &mut Serializer<W, F>) -> anyhow::Result<()>
580    where
581        W: io::Write,
582        F: Formatter,
583    {
584        let (name, operation) = self;
585        ser.serialize_operation_definition(operation, Some(name), true)
586    }
587}
588
589impl Serialize for (Name, FragmentDefinition) {
590    #[inline]
591    fn serialize<W, F>(&self, ser: &mut Serializer<W, F>) -> anyhow::Result<()>
592    where
593        W: io::Write,
594        F: Formatter,
595    {
596        let (name, fragment) = self;
597        ser.serialize_fragment_definition(name, fragment)
598    }
599}
600
601impl_serialize!(ExecutableDocument, serialize_executable_document);
602impl_serialize!(SelectionSet, serialize_selection_set);
603impl_serialize!(Selection, serialize_selection);
604impl_serialize!(Field, serialize_selection_field);
605impl_serialize!(FragmentSpread, serialize_fragment_spread);
606impl_serialize!(InlineFragment, serialize_inline_fragment);
607impl_serialize!(Directive, serialize_directive);
608impl_serialize!(VariableDefinition, serialize_variable_definition);
609impl_serialize!(Type, serialize_type);
610impl_serialize!(ConstValue, serialize_const_value);
611impl_serialize!(TypeCondition, serialize_type_condition);
612impl_serialize!(Name, serialize_name);
613impl_serialize!(Value, serialize_value);
614impl_serialize!(Number, serialize_number);