apollo_encoder/
from_parser.rs

1use std::convert::TryFrom;
2
3use apollo_parser::cst::{self, CstNode};
4use thiserror::Error;
5
6/// Errors that can occur when converting an apollo-parser CST to an apollo-encoder one.
7/// These errors don't give a lot of context at the moment. Before converting CSTs, you
8/// should make sure that your parse tree is complete and valid.
9// TODO(@goto-bus-stop) Would be nice to have some way to show where the error
10// occurred
11#[derive(Debug, Clone, Error)]
12pub enum FromError {
13    /// the parse tree is missing a node
14    #[error("parse tree is missing a node")]
15    MissingNode,
16    /// expected to parse a `i32`
17    #[error("invalid i32")]
18    ParseIntError(#[from] std::num::ParseIntError),
19    /// expected to parse a `f64`
20    #[error("invalid f64")]
21    ParseFloatError(#[from] std::num::ParseFloatError),
22}
23
24impl TryFrom<cst::Value> for crate::Value {
25    type Error = FromError;
26
27    /// Create an apollo-encoder node from an apollo-parser one.
28    ///
29    /// # Errors
30    /// This returns an error if the apollo-parser tree is not valid. The error
31    /// doesn't have much context due to TryFrom API constraints: validate the parse tree before
32    /// using TryFrom if granular errors are important to you.
33    fn try_from(node: cst::Value) -> Result<Self, Self::Error> {
34        let encoder_node = match node {
35            cst::Value::Variable(variable) => Self::Variable(
36                variable
37                    .name()
38                    .ok_or(FromError::MissingNode)?
39                    .text()
40                    .to_string(),
41            ),
42            cst::Value::StringValue(string) => Self::String(string.into()),
43            cst::Value::FloatValue(float) => Self::Float(
44                float
45                    .float_token()
46                    .ok_or(FromError::MissingNode)?
47                    .text()
48                    .parse()?,
49            ),
50            cst::Value::IntValue(int) => Self::Int(
51                int.int_token()
52                    .ok_or(FromError::MissingNode)?
53                    .text()
54                    .parse()?,
55            ),
56            cst::Value::BooleanValue(boolean) => Self::Boolean(boolean.true_token().is_some()),
57            cst::Value::NullValue(_) => Self::Null,
58            cst::Value::EnumValue(enum_) => Self::Enum(enum_.text().to_string()),
59            cst::Value::ListValue(list) => {
60                let encoder_list = list
61                    .values()
62                    .map(Self::try_from)
63                    .collect::<Result<Vec<_>, FromError>>()?;
64                Self::List(encoder_list)
65            }
66            cst::Value::ObjectValue(object) => {
67                let encoder_object = object
68                    .object_fields()
69                    .map(|field| {
70                        let name = field
71                            .name()
72                            .ok_or(FromError::MissingNode)?
73                            .text()
74                            .to_string();
75                        let value = field.value().ok_or(FromError::MissingNode)?.try_into()?;
76                        Ok((name, value))
77                    })
78                    .collect::<Result<Vec<_>, FromError>>()?;
79                Self::Object(encoder_object)
80            }
81        };
82
83        Ok(encoder_node)
84    }
85}
86
87impl TryFrom<cst::DefaultValue> for crate::Value {
88    type Error = FromError;
89
90    /// Create an apollo-encoder node from an apollo-parser one.
91    ///
92    /// # Errors
93    /// This returns an error if the apollo-parser tree is not valid. The error
94    /// doesn't have much context due to TryFrom API constraints: validate the parse tree before
95    /// using TryFrom if granular errors are important to you.
96    fn try_from(node: cst::DefaultValue) -> Result<Self, Self::Error> {
97        node.value().ok_or(FromError::MissingNode)?.try_into()
98    }
99}
100
101impl TryFrom<cst::Directive> for crate::Directive {
102    type Error = FromError;
103
104    /// Create an apollo-encoder node from an apollo-parser one.
105    ///
106    /// # Errors
107    /// This returns an error if the apollo-parser tree is not valid. The error
108    /// doesn't have much context due to TryFrom API constraints: validate the parse tree before
109    /// using TryFrom if granular errors are important to you.
110    fn try_from(node: cst::Directive) -> Result<Self, Self::Error> {
111        let name = node
112            .name()
113            .ok_or(FromError::MissingNode)?
114            .text()
115            .to_string();
116        let mut directive = Self::new(name);
117
118        if let Some(arguments) = node.arguments() {
119            for argument in arguments.arguments() {
120                directive.arg(argument.try_into()?);
121            }
122        }
123
124        Ok(directive)
125    }
126}
127
128impl TryFrom<cst::Argument> for crate::Argument {
129    type Error = FromError;
130
131    /// Create an apollo-encoder node from an apollo-parser one.
132    ///
133    /// # Errors
134    /// This returns an error if the apollo-parser tree is not valid. The error
135    /// doesn't have much context due to TryFrom API constraints: validate the parse tree before
136    /// using TryFrom if granular errors are important to you.
137    fn try_from(node: cst::Argument) -> Result<Self, Self::Error> {
138        let name = node
139            .name()
140            .ok_or(FromError::MissingNode)?
141            .text()
142            .to_string();
143        let value = node.value().ok_or(FromError::MissingNode)?.try_into()?;
144        Ok(crate::Argument::new(name, value))
145    }
146}
147
148impl TryFrom<cst::NamedType> for crate::Type_ {
149    type Error = FromError;
150
151    /// Create an apollo-encoder node from an apollo-parser one.
152    ///
153    /// # Errors
154    /// This returns an error if the apollo-parser tree is not valid. The error
155    /// doesn't have much context due to TryFrom API constraints: validate the parse tree before
156    /// using TryFrom if granular errors are important to you.
157    fn try_from(node: cst::NamedType) -> Result<Self, Self::Error> {
158        Ok(Self::NamedType {
159            name: node
160                .name()
161                .ok_or(FromError::MissingNode)?
162                .text()
163                .to_string(),
164        })
165    }
166}
167
168impl TryFrom<cst::ListType> for crate::Type_ {
169    type Error = FromError;
170
171    /// Create an apollo-encoder node from an apollo-parser one.
172    ///
173    /// # Errors
174    /// This returns an error if the apollo-parser tree is not valid. The error
175    /// doesn't have much context due to TryFrom API constraints: validate the parse tree before
176    /// using TryFrom if granular errors are important to you.
177    fn try_from(node: cst::ListType) -> Result<Self, Self::Error> {
178        Ok(Self::List {
179            ty: Box::new(node.ty().ok_or(FromError::MissingNode)?.try_into()?),
180        })
181    }
182}
183
184impl TryFrom<cst::NonNullType> for crate::Type_ {
185    type Error = FromError;
186
187    /// Create an apollo-encoder node from an apollo-parser one.
188    ///
189    /// # Errors
190    /// This returns an error if the apollo-parser tree is not valid. The error
191    /// doesn't have much context due to TryFrom API constraints: validate the parse tree before
192    /// using TryFrom if granular errors are important to you.
193    fn try_from(node: cst::NonNullType) -> Result<Self, Self::Error> {
194        let named_type = node
195            .named_type()
196            .ok_or(FromError::MissingNode)
197            .and_then(|ty| ty.try_into());
198        let list_type = node
199            .list_type()
200            .ok_or(FromError::MissingNode)
201            .and_then(|ty| ty.try_into());
202
203        Ok(Self::NonNull {
204            ty: Box::new(named_type.or(list_type)?),
205        })
206    }
207}
208
209impl TryFrom<cst::Type> for crate::Type_ {
210    type Error = FromError;
211
212    /// Create an apollo-encoder node from an apollo-parser one.
213    ///
214    /// # Errors
215    /// This returns an error if the apollo-parser tree is not valid. The error
216    /// doesn't have much context due to TryFrom API constraints: validate the parse tree before
217    /// using TryFrom if granular errors are important to you.
218    fn try_from(node: cst::Type) -> Result<Self, Self::Error> {
219        match node {
220            cst::Type::NamedType(ty) => ty.try_into(),
221            cst::Type::ListType(ty) => ty.try_into(),
222            cst::Type::NonNullType(ty) => ty.try_into(),
223        }
224    }
225}
226
227impl TryFrom<cst::InputValueDefinition> for crate::InputValueDefinition {
228    type Error = FromError;
229
230    /// Create an apollo-encoder node from an apollo-parser one.
231    ///
232    /// # Errors
233    /// This returns an error if the apollo-parser tree is not valid. The error
234    /// doesn't have much context due to TryFrom API constraints: validate the parse tree before
235    /// using TryFrom if granular errors are important to you.
236    fn try_from(node: cst::InputValueDefinition) -> Result<Self, Self::Error> {
237        let name = node
238            .name()
239            .ok_or(FromError::MissingNode)?
240            .text()
241            .to_string();
242        let ty = node.ty().ok_or(FromError::MissingNode)?;
243        let mut encoder_node = Self::new(name, ty.try_into()?);
244
245        if let Some(description) = node.description() {
246            encoder_node.description(
247                description
248                    .string_value()
249                    .ok_or(FromError::MissingNode)?
250                    .into(),
251            );
252        }
253
254        if let Some(default_value) = node.default_value() {
255            // TODO represent this as a Value enum in encoder?
256            encoder_node.default_value(
257                default_value
258                    .value()
259                    .ok_or(FromError::MissingNode)?
260                    .source_string(),
261            );
262        }
263
264        if let Some(directives) = node.directives() {
265            for directive in directives.directives() {
266                encoder_node.directive(directive.try_into()?);
267            }
268        }
269
270        Ok(encoder_node)
271    }
272}
273
274impl TryFrom<cst::ArgumentsDefinition> for crate::ArgumentsDefinition {
275    type Error = FromError;
276
277    /// Create an apollo-encoder node from an apollo-parser one.
278    ///
279    /// # Errors
280    /// This returns an error if the apollo-parser tree is not valid. The error
281    /// doesn't have much context due to TryFrom API constraints: validate the parse tree before
282    /// using TryFrom if granular errors are important to you.
283    fn try_from(node: cst::ArgumentsDefinition) -> Result<Self, Self::Error> {
284        let input_values = node
285            .input_value_definitions()
286            .map(|input_value| input_value.try_into())
287            .collect::<Result<Vec<_>, FromError>>()?;
288
289        Ok(Self::with_values(input_values))
290    }
291}
292
293impl TryFrom<cst::FieldDefinition> for crate::FieldDefinition {
294    type Error = FromError;
295
296    /// Create an apollo-encoder node from an apollo-parser one.
297    ///
298    /// # Errors
299    /// This returns an error if the apollo-parser tree is not valid. The error
300    /// doesn't have much context due to TryFrom API constraints: validate the parse tree before
301    /// using TryFrom if granular errors are important to you.
302    fn try_from(node: cst::FieldDefinition) -> Result<Self, Self::Error> {
303        let name = node
304            .name()
305            .ok_or(FromError::MissingNode)?
306            .text()
307            .to_string();
308        let ty = node.ty().ok_or(FromError::MissingNode)?.try_into()?;
309        let mut encoder_node = Self::new(name, ty);
310
311        if let Some(arguments_definition) = node.arguments_definition() {
312            for input_value in arguments_definition.input_value_definitions() {
313                encoder_node.arg(input_value.try_into()?);
314            }
315        }
316
317        if let Some(directives) = node.directives() {
318            for directive in directives.directives() {
319                encoder_node.directive(directive.try_into()?);
320            }
321        }
322
323        Ok(encoder_node)
324    }
325}
326
327impl TryFrom<cst::TypeCondition> for crate::TypeCondition {
328    type Error = FromError;
329
330    /// Create an apollo-encoder node from an apollo-parser one.
331    ///
332    /// # Errors
333    /// This returns an error if the apollo-parser tree is not valid. The error
334    /// doesn't have much context due to TryFrom API constraints: validate the parse tree before
335    /// using TryFrom if granular errors are important to you.
336    fn try_from(node: cst::TypeCondition) -> Result<Self, Self::Error> {
337        let named_type = node.named_type().ok_or(FromError::MissingNode)?;
338        let name = named_type
339            .name()
340            .ok_or(FromError::MissingNode)?
341            .text()
342            .to_string();
343        Ok(Self::new(name))
344    }
345}
346
347impl TryFrom<cst::Field> for crate::Field {
348    type Error = FromError;
349
350    /// Create an apollo-encoder node from an apollo-parser one.
351    ///
352    /// # Errors
353    /// This returns an error if the apollo-parser tree is not valid. The error
354    /// doesn't have much context due to TryFrom API constraints: validate the parse tree before
355    /// using TryFrom if granular errors are important to you.
356    fn try_from(node: cst::Field) -> Result<Self, Self::Error> {
357        let name = node
358            .name()
359            .ok_or(FromError::MissingNode)?
360            .text()
361            .to_string();
362
363        let mut encoder_node = Self::new(name);
364
365        if let Some(alias) = node.alias() {
366            let alias = alias
367                .name()
368                .ok_or(FromError::MissingNode)?
369                .text()
370                .to_string();
371            encoder_node.alias(Some(alias));
372        }
373
374        if let Some(arguments) = node.arguments() {
375            for argument in arguments.arguments() {
376                encoder_node.argument(argument.try_into()?);
377            }
378        }
379
380        if let Some(directives) = node.directives() {
381            for directive in directives.directives() {
382                encoder_node.directive(directive.try_into()?);
383            }
384        }
385
386        let selection_set = node
387            .selection_set()
388            .map(|selection_set| selection_set.try_into())
389            .transpose()?;
390        encoder_node.selection_set(selection_set);
391
392        Ok(encoder_node)
393    }
394}
395
396impl TryFrom<cst::FragmentSpread> for crate::FragmentSpread {
397    type Error = FromError;
398
399    /// Create an apollo-encoder node from an apollo-parser one.
400    ///
401    /// # Errors
402    /// This returns an error if the apollo-parser tree is not valid. The error
403    /// doesn't have much context due to TryFrom API constraints: validate the parse tree before
404    /// using TryFrom if granular errors are important to you.
405    fn try_from(node: cst::FragmentSpread) -> Result<Self, Self::Error> {
406        let name = node
407            .fragment_name()
408            .and_then(|fragment_name| fragment_name.name())
409            .ok_or(FromError::MissingNode)?
410            .text()
411            .to_string();
412        let mut encoder_node = Self::new(name);
413        if let Some(directives) = node.directives() {
414            for directive in directives.directives() {
415                encoder_node.directive(directive.try_into()?);
416            }
417        }
418        Ok(encoder_node)
419    }
420}
421
422impl TryFrom<cst::InlineFragment> for crate::InlineFragment {
423    type Error = FromError;
424
425    /// Create an apollo-encoder node from an apollo-parser one.
426    ///
427    /// # Errors
428    /// This returns an error if the apollo-parser tree is not valid. The error
429    /// doesn't have much context due to TryFrom API constraints: validate the parse tree before
430    /// using TryFrom if granular errors are important to you.
431    fn try_from(node: cst::InlineFragment) -> Result<Self, Self::Error> {
432        let selection_set = node
433            .selection_set()
434            .ok_or(FromError::MissingNode)?
435            .try_into()?;
436        let mut encoder_node = Self::new(selection_set);
437
438        let type_condition = node
439            .type_condition()
440            .map(|condition| condition.try_into())
441            .transpose()?;
442        encoder_node.type_condition(type_condition);
443
444        if let Some(directives) = node.directives() {
445            for directive in directives.directives() {
446                encoder_node.directive(directive.try_into()?);
447            }
448        }
449
450        Ok(encoder_node)
451    }
452}
453
454impl TryFrom<cst::Selection> for crate::Selection {
455    type Error = FromError;
456
457    /// Create an apollo-encoder node from an apollo-parser one.
458    ///
459    /// # Errors
460    /// This returns an error if the apollo-parser tree is not valid. The error
461    /// doesn't have much context due to TryFrom API constraints: validate the parse tree before
462    /// using TryFrom if granular errors are important to you.
463    fn try_from(node: cst::Selection) -> Result<Self, Self::Error> {
464        let encoder_node = match node {
465            cst::Selection::Field(field) => Self::Field(field.try_into()?),
466            cst::Selection::FragmentSpread(fragment) => Self::FragmentSpread(fragment.try_into()?),
467            cst::Selection::InlineFragment(fragment) => Self::InlineFragment(fragment.try_into()?),
468        };
469
470        Ok(encoder_node)
471    }
472}
473
474impl TryFrom<cst::SelectionSet> for crate::SelectionSet {
475    type Error = FromError;
476
477    /// Create an apollo-encoder node from an apollo-parser one.
478    ///
479    /// # Errors
480    /// This returns an error if the apollo-parser tree is not valid. The error
481    /// doesn't have much context due to TryFrom API constraints: validate the parse tree before
482    /// using TryFrom if granular errors are important to you.
483    fn try_from(node: cst::SelectionSet) -> Result<Self, Self::Error> {
484        let selections = node
485            .selections()
486            .map(|selection| selection.try_into())
487            .collect::<Result<Vec<_>, FromError>>()?;
488
489        Ok(Self::with_selections(selections))
490    }
491}
492
493impl TryFrom<cst::OperationType> for crate::OperationType {
494    type Error = FromError;
495
496    /// Create an apollo-encoder node from an apollo-parser one.
497    ///
498    /// # Errors
499    /// This returns an error if the apollo-parser tree is not valid. The error
500    /// doesn't have much context due to TryFrom API constraints: validate the parse tree before
501    /// using TryFrom if granular errors are important to you.
502    fn try_from(node: cst::OperationType) -> Result<Self, Self::Error> {
503        if node.query_token().is_some() {
504            Ok(Self::Query)
505        } else if node.mutation_token().is_some() {
506            Ok(Self::Mutation)
507        } else if node.subscription_token().is_some() {
508            Ok(Self::Subscription)
509        } else {
510            Err(FromError::MissingNode)
511        }
512    }
513}
514
515impl TryFrom<cst::VariableDefinition> for crate::VariableDefinition {
516    type Error = FromError;
517
518    /// Create an apollo-encoder node from an apollo-parser one.
519    ///
520    /// # Errors
521    /// This returns an error if the apollo-parser tree is not valid. The error
522    /// doesn't have much context due to TryFrom API constraints: validate the parse tree before
523    /// using TryFrom if granular errors are important to you.
524    fn try_from(node: cst::VariableDefinition) -> Result<Self, Self::Error> {
525        let name = node
526            .variable()
527            .ok_or(FromError::MissingNode)?
528            .name()
529            .ok_or(FromError::MissingNode)?
530            .text()
531            .to_string();
532        let ty = node.ty().ok_or(FromError::MissingNode)?.try_into()?;
533
534        let mut encoder_node = Self::new(name, ty);
535
536        if let Some(default_value) = node.default_value() {
537            encoder_node.default_value(default_value.try_into()?);
538        }
539
540        if let Some(directives) = node.directives() {
541            for directive in directives.directives() {
542                encoder_node.directive(directive.try_into()?);
543            }
544        }
545
546        Ok(encoder_node)
547    }
548}
549
550impl TryFrom<cst::OperationDefinition> for crate::OperationDefinition {
551    type Error = FromError;
552
553    /// Create an apollo-encoder node from an apollo-parser one.
554    ///
555    /// # Errors
556    /// This returns an error if the apollo-parser tree is not valid. The error
557    /// doesn't have much context due to TryFrom API constraints: validate the parse tree before
558    /// using TryFrom if granular errors are important to you.
559    fn try_from(node: cst::OperationDefinition) -> Result<Self, Self::Error> {
560        let operation_type = node
561            .operation_type()
562            .ok_or(FromError::MissingNode)?
563            .try_into()?;
564        let selection_set = node
565            .selection_set()
566            .ok_or(FromError::MissingNode)?
567            .try_into()?;
568
569        let mut encoder_node = Self::new(operation_type, selection_set);
570
571        if let Some(name) = node.name() {
572            encoder_node.name(Some(name.text().to_string()));
573        }
574
575        if let Some(variable_definitions) = node.variable_definitions() {
576            for variable_definition in variable_definitions.variable_definitions() {
577                encoder_node.variable_definition(variable_definition.try_into()?);
578            }
579        }
580
581        if let Some(directives) = node.directives() {
582            for directive in directives.directives() {
583                encoder_node.directive(directive.try_into()?);
584            }
585        }
586
587        Ok(encoder_node)
588    }
589}
590
591impl TryFrom<cst::FragmentDefinition> for crate::FragmentDefinition {
592    type Error = FromError;
593
594    /// Create an apollo-encoder node from an apollo-parser one.
595    ///
596    /// # Errors
597    /// This returns an error if the apollo-parser tree is not valid. The error
598    /// doesn't have much context due to TryFrom API constraints: validate the parse tree before
599    /// using TryFrom if granular errors are important to you.
600    fn try_from(node: cst::FragmentDefinition) -> Result<Self, Self::Error> {
601        let name = node
602            .fragment_name()
603            .ok_or(FromError::MissingNode)?
604            .name()
605            .ok_or(FromError::MissingNode)?
606            .text()
607            .to_string();
608        let type_condition = node
609            .type_condition()
610            .ok_or(FromError::MissingNode)?
611            .try_into()?;
612        let selection_set = node
613            .selection_set()
614            .ok_or(FromError::MissingNode)?
615            .try_into()?;
616
617        let mut encoder_node = Self::new(name, type_condition, selection_set);
618        if let Some(directives) = node.directives() {
619            for directive in directives.directives() {
620                encoder_node.directive(directive.try_into()?);
621            }
622        }
623
624        Ok(encoder_node)
625    }
626}
627
628impl TryFrom<cst::DirectiveDefinition> for crate::DirectiveDefinition {
629    type Error = FromError;
630
631    /// Create an apollo-encoder node from an apollo-parser one.
632    ///
633    /// # Errors
634    /// This returns an error if the apollo-parser tree is not valid. The error
635    /// doesn't have much context due to TryFrom API constraints: validate the parse tree before
636    /// using TryFrom if granular errors are important to you.
637    fn try_from(node: cst::DirectiveDefinition) -> Result<Self, Self::Error> {
638        let name = node
639            .name()
640            .ok_or(FromError::MissingNode)?
641            .text()
642            .to_string();
643
644        let mut encoder_node = Self::new(name);
645
646        let description = node
647            .description()
648            .and_then(|description| description.string_value())
649            .map(|string| string.into());
650        if let Some(description) = description {
651            encoder_node.description(description);
652        }
653
654        if let Some(arguments_definition) = node.arguments_definition() {
655            for input_value in arguments_definition.input_value_definitions() {
656                encoder_node.arg(input_value.try_into()?);
657            }
658        }
659
660        if let Some(directive_locations) = node.directive_locations() {
661            let locations = directive_locations
662                .directive_locations()
663                .map(|location| location.text().map(|token| token.to_string()));
664            for location in locations {
665                // TODO(@goto-bus-stop) This actually indicates that a directive location had an
666                // unknown value, not that it was missing
667                let location = location.ok_or(FromError::MissingNode)?;
668                encoder_node.location(location);
669            }
670        }
671
672        if node.repeatable_token().is_some() {
673            encoder_node.repeatable();
674        }
675
676        Ok(encoder_node)
677    }
678}
679
680fn apply_root_operation_type_definitions(
681    encoder_node: &mut crate::SchemaDefinition,
682    type_definitions: impl Iterator<Item = cst::RootOperationTypeDefinition>,
683) -> Result<(), FromError> {
684    for root in type_definitions {
685        let operation_type = root.operation_type().ok_or(FromError::MissingNode)?;
686        let name = root
687            .named_type()
688            .ok_or(FromError::MissingNode)?
689            .name()
690            .ok_or(FromError::MissingNode)?
691            .text()
692            .to_string();
693        if operation_type.query_token().is_some() {
694            encoder_node.query(name);
695        } else if operation_type.mutation_token().is_some() {
696            encoder_node.mutation(name);
697        } else if operation_type.subscription_token().is_some() {
698            encoder_node.subscription(name);
699        } else {
700            return Err(FromError::MissingNode);
701        }
702    }
703
704    Ok(())
705}
706
707impl TryFrom<cst::SchemaDefinition> for crate::SchemaDefinition {
708    type Error = FromError;
709
710    /// Create an apollo-encoder node from an apollo-parser one.
711    ///
712    /// # Errors
713    /// This returns an error if the apollo-parser tree is not valid. The error
714    /// doesn't have much context due to TryFrom API constraints: validate the parse tree before
715    /// using TryFrom if granular errors are important to you.
716    fn try_from(node: cst::SchemaDefinition) -> Result<Self, Self::Error> {
717        let mut encoder_node = Self::new();
718
719        let description = node
720            .description()
721            .and_then(|description| description.string_value())
722            .map(|string| string.into());
723        if let Some(description) = description {
724            encoder_node.description(description);
725        }
726
727        if let Some(directives) = node.directives() {
728            for directive in directives.directives() {
729                encoder_node.directive(directive.try_into()?);
730            }
731        }
732
733        apply_root_operation_type_definitions(
734            &mut encoder_node,
735            node.root_operation_type_definitions(),
736        )?;
737
738        Ok(encoder_node)
739    }
740}
741
742impl TryFrom<cst::ScalarTypeDefinition> for crate::ScalarDefinition {
743    type Error = FromError;
744
745    /// Create an apollo-encoder node from an apollo-parser one.
746    ///
747    /// # Errors
748    /// This returns an error if the apollo-parser tree is not valid. The error
749    /// doesn't have much context due to TryFrom API constraints: validate the parse tree before
750    /// using TryFrom if granular errors are important to you.
751    fn try_from(node: cst::ScalarTypeDefinition) -> Result<Self, Self::Error> {
752        let name = node
753            .name()
754            .ok_or(FromError::MissingNode)?
755            .text()
756            .to_string();
757        let mut encoder_node = Self::new(name);
758
759        let description = node
760            .description()
761            .and_then(|description| description.string_value())
762            .map(|string| string.into());
763        if let Some(description) = description {
764            encoder_node.description(description);
765        }
766
767        if let Some(directives) = node.directives() {
768            for directive in directives.directives() {
769                encoder_node.directive(directive.try_into()?);
770            }
771        }
772
773        Ok(encoder_node)
774    }
775}
776
777impl TryFrom<cst::ObjectTypeDefinition> for crate::ObjectDefinition {
778    type Error = FromError;
779
780    /// Create an apollo-encoder node from an apollo-parser one.
781    ///
782    /// # Errors
783    /// This returns an error if the apollo-parser tree is not valid. The error
784    /// doesn't have much context due to TryFrom API constraints: validate the parse tree before
785    /// using TryFrom if granular errors are important to you.
786    fn try_from(node: cst::ObjectTypeDefinition) -> Result<Self, Self::Error> {
787        let name = node
788            .name()
789            .ok_or(FromError::MissingNode)?
790            .text()
791            .to_string();
792        let mut encoder_node = Self::new(name);
793
794        let description = node
795            .description()
796            .and_then(|description| description.string_value())
797            .map(|string| string.into());
798        if let Some(description) = description {
799            encoder_node.description(description);
800        }
801
802        if let Some(directives) = node.directives() {
803            for directive in directives.directives() {
804                encoder_node.directive(directive.try_into()?);
805            }
806        }
807
808        if let Some(implements_interfaces) = node.implements_interfaces() {
809            for implements in implements_interfaces.named_types() {
810                let name = implements
811                    .name()
812                    .ok_or(FromError::MissingNode)?
813                    .text()
814                    .to_string();
815                encoder_node.interface(name);
816            }
817        }
818
819        if let Some(field_definitions) = node.fields_definition() {
820            for field_definition in field_definitions.field_definitions() {
821                encoder_node.field(field_definition.try_into()?);
822            }
823        }
824
825        Ok(encoder_node)
826    }
827}
828
829impl TryFrom<cst::InterfaceTypeDefinition> for crate::InterfaceDefinition {
830    type Error = FromError;
831
832    /// Create an apollo-encoder node from an apollo-parser one.
833    ///
834    /// # Errors
835    /// This returns an error if the apollo-parser tree is not valid. The error
836    /// doesn't have much context due to TryFrom API constraints: validate the parse tree before
837    /// using TryFrom if granular errors are important to you.
838    fn try_from(node: cst::InterfaceTypeDefinition) -> Result<Self, Self::Error> {
839        let name = node
840            .name()
841            .ok_or(FromError::MissingNode)?
842            .text()
843            .to_string();
844        let mut encoder_node = Self::new(name);
845
846        let description = node
847            .description()
848            .and_then(|description| description.string_value())
849            .map(|string| string.into());
850        if let Some(description) = description {
851            encoder_node.description(description);
852        }
853
854        if let Some(directives) = node.directives() {
855            for directive in directives.directives() {
856                encoder_node.directive(directive.try_into()?);
857            }
858        }
859
860        if let Some(implements_interfaces) = node.implements_interfaces() {
861            for implements in implements_interfaces.named_types() {
862                let name = implements
863                    .name()
864                    .ok_or(FromError::MissingNode)?
865                    .text()
866                    .to_string();
867                encoder_node.interface(name);
868            }
869        }
870
871        if let Some(field_definitions) = node.fields_definition() {
872            for field_definition in field_definitions.field_definitions() {
873                encoder_node.field(field_definition.try_into()?);
874            }
875        }
876
877        Ok(encoder_node)
878    }
879}
880
881impl TryFrom<cst::UnionTypeDefinition> for crate::UnionDefinition {
882    type Error = FromError;
883
884    /// Create an apollo-encoder node from an apollo-parser one.
885    ///
886    /// # Errors
887    /// This returns an error if the apollo-parser tree is not valid. The error
888    /// doesn't have much context due to TryFrom API constraints: validate the parse tree before
889    /// using TryFrom if granular errors are important to you.
890    fn try_from(node: cst::UnionTypeDefinition) -> Result<Self, Self::Error> {
891        let name = node
892            .name()
893            .ok_or(FromError::MissingNode)?
894            .text()
895            .to_string();
896        let mut encoder_node = Self::new(name);
897
898        let description = node
899            .description()
900            .and_then(|description| description.string_value())
901            .map(|string| string.into());
902        if let Some(description) = description {
903            encoder_node.description(description);
904        }
905
906        if let Some(directives) = node.directives() {
907            for directive in directives.directives() {
908                encoder_node.directive(directive.try_into()?);
909            }
910        }
911
912        if let Some(members) = node.union_member_types() {
913            for member in members.named_types() {
914                encoder_node.member(
915                    member
916                        .name()
917                        .ok_or(FromError::MissingNode)?
918                        .text()
919                        .to_string(),
920                );
921            }
922        }
923
924        Ok(encoder_node)
925    }
926}
927
928impl TryFrom<cst::EnumValueDefinition> for crate::EnumValue {
929    type Error = FromError;
930
931    /// Create an apollo-encoder node from an apollo-parser one.
932    ///
933    /// # Errors
934    /// This returns an error if the apollo-parser tree is not valid. The error
935    /// doesn't have much context due to TryFrom API constraints: validate the parse tree before
936    /// using TryFrom if granular errors are important to you.
937    fn try_from(node: cst::EnumValueDefinition) -> Result<Self, Self::Error> {
938        let name = node
939            .enum_value()
940            .ok_or(FromError::MissingNode)?
941            .name()
942            .ok_or(FromError::MissingNode)?
943            .text()
944            .to_string();
945        let mut encoder_node = Self::new(name);
946
947        let description = node
948            .description()
949            .and_then(|description| description.string_value())
950            .map(|string| string.into());
951        if let Some(description) = description {
952            encoder_node.description(description);
953        }
954
955        if let Some(directives) = node.directives() {
956            for directive in directives.directives() {
957                encoder_node.directive(directive.try_into()?);
958            }
959        }
960
961        Ok(encoder_node)
962    }
963}
964
965impl TryFrom<cst::EnumTypeDefinition> for crate::EnumDefinition {
966    type Error = FromError;
967
968    /// Create an apollo-encoder node from an apollo-parser one.
969    ///
970    /// # Errors
971    /// This returns an error if the apollo-parser tree is not valid. The error
972    /// doesn't have much context due to TryFrom API constraints: validate the parse tree before
973    /// using TryFrom if granular errors are important to you.
974    fn try_from(node: cst::EnumTypeDefinition) -> Result<Self, Self::Error> {
975        let name = node
976            .name()
977            .ok_or(FromError::MissingNode)?
978            .text()
979            .to_string();
980        let mut encoder_node = Self::new(name);
981
982        let description = node
983            .description()
984            .and_then(|description| description.string_value())
985            .map(|string| string.into());
986        if let Some(description) = description {
987            encoder_node.description(description);
988        }
989
990        if let Some(directives) = node.directives() {
991            for directive in directives.directives() {
992                encoder_node.directive(directive.try_into()?);
993            }
994        }
995
996        if let Some(values) = node.enum_values_definition() {
997            for value in values.enum_value_definitions() {
998                encoder_node.value(value.try_into()?);
999            }
1000        }
1001
1002        Ok(encoder_node)
1003    }
1004}
1005
1006impl TryFrom<cst::InputValueDefinition> for crate::InputField {
1007    type Error = FromError;
1008
1009    /// Create an apollo-encoder node from an apollo-parser one.
1010    ///
1011    /// # Errors
1012    /// This returns an error if the apollo-parser tree is not valid. The error
1013    /// doesn't have much context due to TryFrom API constraints: validate the parse tree before
1014    /// using TryFrom if granular errors are important to you.
1015    fn try_from(node: cst::InputValueDefinition) -> Result<Self, Self::Error> {
1016        let name = node
1017            .name()
1018            .ok_or(FromError::MissingNode)?
1019            .text()
1020            .to_string();
1021        let ty = node.ty().ok_or(FromError::MissingNode)?;
1022        let mut encoder_node = Self::new(name, ty.try_into()?);
1023
1024        if let Some(description) = node.description() {
1025            encoder_node.description(
1026                description
1027                    .string_value()
1028                    .ok_or(FromError::MissingNode)?
1029                    .into(),
1030            );
1031        }
1032
1033        if let Some(default_value) = node.default_value() {
1034            // TODO represent this as a Value enum in encoder?
1035            encoder_node.default_value(
1036                default_value
1037                    .value()
1038                    .ok_or(FromError::MissingNode)?
1039                    .source_string(),
1040            );
1041        }
1042
1043        if let Some(directives) = node.directives() {
1044            for directive in directives.directives() {
1045                encoder_node.directive(directive.try_into()?);
1046            }
1047        }
1048
1049        Ok(encoder_node)
1050    }
1051}
1052
1053impl TryFrom<cst::InputObjectTypeDefinition> for crate::InputObjectDefinition {
1054    type Error = FromError;
1055
1056    /// Create an apollo-encoder node from an apollo-parser one.
1057    ///
1058    /// # Errors
1059    /// This returns an error if the apollo-parser tree is not valid. The error
1060    /// doesn't have much context due to TryFrom API constraints: validate the parse tree before
1061    /// using TryFrom if granular errors are important to you.
1062    fn try_from(node: cst::InputObjectTypeDefinition) -> Result<Self, Self::Error> {
1063        let name = node
1064            .name()
1065            .ok_or(FromError::MissingNode)?
1066            .text()
1067            .to_string();
1068        let mut encoder_node = Self::new(name);
1069
1070        let description = node
1071            .description()
1072            .and_then(|description| description.string_value())
1073            .and_then(|string| string.try_into().ok());
1074        if let Some(description) = description {
1075            encoder_node.description(description);
1076        }
1077
1078        if let Some(directives) = node.directives() {
1079            for directive in directives.directives() {
1080                encoder_node.directive(directive.try_into()?);
1081            }
1082        }
1083
1084        if let Some(field_definitions) = node.input_fields_definition() {
1085            for field_definition in field_definitions.input_value_definitions() {
1086                encoder_node.field(field_definition.try_into()?);
1087            }
1088        }
1089
1090        Ok(encoder_node)
1091    }
1092}
1093
1094impl TryFrom<cst::SchemaExtension> for crate::SchemaDefinition {
1095    type Error = FromError;
1096
1097    /// Create an apollo-encoder node from an apollo-parser one.
1098    ///
1099    /// # Errors
1100    /// This returns an error if the apollo-parser tree is not valid. The error
1101    /// doesn't have much context due to TryFrom API constraints: validate the parse tree before
1102    /// using TryFrom if granular errors are important to you.
1103    fn try_from(node: cst::SchemaExtension) -> Result<Self, Self::Error> {
1104        let mut encoder_node = Self::new();
1105
1106        if let Some(directives) = node.directives() {
1107            for directive in directives.directives() {
1108                encoder_node.directive(directive.try_into()?);
1109            }
1110        }
1111
1112        apply_root_operation_type_definitions(
1113            &mut encoder_node,
1114            node.root_operation_type_definitions(),
1115        )?;
1116
1117        encoder_node.extend();
1118
1119        Ok(encoder_node)
1120    }
1121}
1122
1123impl TryFrom<cst::ScalarTypeExtension> for crate::ScalarDefinition {
1124    type Error = FromError;
1125
1126    /// Create an apollo-encoder node from an apollo-parser one.
1127    ///
1128    /// # Errors
1129    /// This returns an error if the apollo-parser tree is not valid. The error
1130    /// doesn't have much context due to TryFrom API constraints: validate the parse tree before
1131    /// using TryFrom if granular errors are important to you.
1132    fn try_from(node: cst::ScalarTypeExtension) -> Result<Self, Self::Error> {
1133        let name = node
1134            .name()
1135            .ok_or(FromError::MissingNode)?
1136            .text()
1137            .to_string();
1138        let mut encoder_node = Self::new(name);
1139
1140        if let Some(directives) = node.directives() {
1141            for directive in directives.directives() {
1142                encoder_node.directive(directive.try_into()?);
1143            }
1144        }
1145
1146        encoder_node.extend();
1147
1148        Ok(encoder_node)
1149    }
1150}
1151
1152impl TryFrom<cst::ObjectTypeExtension> for crate::ObjectDefinition {
1153    type Error = FromError;
1154
1155    /// Create an apollo-encoder node from an apollo-parser one.
1156    ///
1157    /// # Errors
1158    /// This returns an error if the apollo-parser tree is not valid. The error
1159    /// doesn't have much context due to TryFrom API constraints: validate the parse tree before
1160    /// using TryFrom if granular errors are important to you.
1161    fn try_from(node: cst::ObjectTypeExtension) -> Result<Self, Self::Error> {
1162        let name = node
1163            .name()
1164            .ok_or(FromError::MissingNode)?
1165            .text()
1166            .to_string();
1167        let mut encoder_node = Self::new(name);
1168
1169        if let Some(directives) = node.directives() {
1170            for directive in directives.directives() {
1171                encoder_node.directive(directive.try_into()?);
1172            }
1173        }
1174
1175        if let Some(implements_interfaces) = node.implements_interfaces() {
1176            for implements in implements_interfaces.named_types() {
1177                let name = implements
1178                    .name()
1179                    .ok_or(FromError::MissingNode)?
1180                    .text()
1181                    .to_string();
1182                encoder_node.interface(name);
1183            }
1184        }
1185
1186        if let Some(field_definitions) = node.fields_definition() {
1187            for field_definition in field_definitions.field_definitions() {
1188                encoder_node.field(field_definition.try_into()?);
1189            }
1190        }
1191
1192        encoder_node.extend();
1193
1194        Ok(encoder_node)
1195    }
1196}
1197
1198impl TryFrom<cst::InterfaceTypeExtension> for crate::InterfaceDefinition {
1199    type Error = FromError;
1200
1201    /// Create an apollo-encoder node from an apollo-parser one.
1202    ///
1203    /// # Errors
1204    /// This returns an error if the apollo-parser tree is not valid. The error
1205    /// doesn't have much context due to TryFrom API constraints: validate the parse tree before
1206    /// using TryFrom if granular errors are important to you.
1207    fn try_from(node: cst::InterfaceTypeExtension) -> Result<Self, Self::Error> {
1208        let name = node
1209            .name()
1210            .ok_or(FromError::MissingNode)?
1211            .text()
1212            .to_string();
1213        let mut encoder_node = Self::new(name);
1214
1215        if let Some(directives) = node.directives() {
1216            for directive in directives.directives() {
1217                encoder_node.directive(directive.try_into()?);
1218            }
1219        }
1220
1221        if let Some(implements_interfaces) = node.implements_interfaces() {
1222            for implements in implements_interfaces.named_types() {
1223                let name = implements
1224                    .name()
1225                    .ok_or(FromError::MissingNode)?
1226                    .text()
1227                    .to_string();
1228                encoder_node.interface(name);
1229            }
1230        }
1231
1232        if let Some(field_definitions) = node.fields_definition() {
1233            for field_definition in field_definitions.field_definitions() {
1234                encoder_node.field(field_definition.try_into()?);
1235            }
1236        }
1237
1238        encoder_node.extend();
1239
1240        Ok(encoder_node)
1241    }
1242}
1243
1244impl TryFrom<cst::UnionTypeExtension> for crate::UnionDefinition {
1245    type Error = FromError;
1246
1247    /// Create an apollo-encoder node from an apollo-parser one.
1248    ///
1249    /// # Errors
1250    /// This returns an error if the apollo-parser tree is not valid. The error
1251    /// doesn't have much context due to TryFrom API constraints: validate the parse tree before
1252    /// using TryFrom if granular errors are important to you.
1253    fn try_from(node: cst::UnionTypeExtension) -> Result<Self, Self::Error> {
1254        let name = node
1255            .name()
1256            .ok_or(FromError::MissingNode)?
1257            .text()
1258            .to_string();
1259        let mut encoder_node = Self::new(name);
1260
1261        if let Some(directives) = node.directives() {
1262            for directive in directives.directives() {
1263                encoder_node.directive(directive.try_into()?);
1264            }
1265        }
1266
1267        if let Some(members) = node.union_member_types() {
1268            for member in members.named_types() {
1269                encoder_node.member(
1270                    member
1271                        .name()
1272                        .ok_or(FromError::MissingNode)?
1273                        .text()
1274                        .to_string(),
1275                );
1276            }
1277        }
1278
1279        encoder_node.extend();
1280
1281        Ok(encoder_node)
1282    }
1283}
1284
1285impl TryFrom<cst::EnumTypeExtension> for crate::EnumDefinition {
1286    type Error = FromError;
1287
1288    /// Create an apollo-encoder node from an apollo-parser one.
1289    ///
1290    /// # Errors
1291    /// This returns an error if the apollo-parser tree is not valid. The error
1292    /// doesn't have much context due to TryFrom API constraints: validate the parse tree before
1293    /// using TryFrom if granular errors are important to you.
1294    fn try_from(node: cst::EnumTypeExtension) -> Result<Self, Self::Error> {
1295        let name = node
1296            .name()
1297            .ok_or(FromError::MissingNode)?
1298            .text()
1299            .to_string();
1300        let mut encoder_node = Self::new(name);
1301
1302        if let Some(directives) = node.directives() {
1303            for directive in directives.directives() {
1304                encoder_node.directive(directive.try_into()?);
1305            }
1306        }
1307
1308        if let Some(values) = node.enum_values_definition() {
1309            for value in values.enum_value_definitions() {
1310                encoder_node.value(value.try_into()?);
1311            }
1312        }
1313
1314        encoder_node.extend();
1315
1316        Ok(encoder_node)
1317    }
1318}
1319
1320impl TryFrom<cst::InputObjectTypeExtension> for crate::InputObjectDefinition {
1321    type Error = FromError;
1322
1323    /// Create an apollo-encoder node from an apollo-parser one.
1324    ///
1325    /// # Errors
1326    /// This returns an error if the apollo-parser tree is not valid. The error
1327    /// doesn't have much context due to TryFrom API constraints: validate the parse tree before
1328    /// using TryFrom if granular errors are important to you.
1329    fn try_from(node: cst::InputObjectTypeExtension) -> Result<Self, Self::Error> {
1330        let name = node
1331            .name()
1332            .ok_or(FromError::MissingNode)?
1333            .text()
1334            .to_string();
1335        let mut encoder_node = Self::new(name);
1336
1337        if let Some(directives) = node.directives() {
1338            for directive in directives.directives() {
1339                encoder_node.directive(directive.try_into()?);
1340            }
1341        }
1342
1343        if let Some(field_definitions) = node.input_fields_definition() {
1344            for field_definition in field_definitions.input_value_definitions() {
1345                encoder_node.field(field_definition.try_into()?);
1346            }
1347        }
1348
1349        encoder_node.extend();
1350
1351        Ok(encoder_node)
1352    }
1353}
1354
1355impl TryFrom<cst::Document> for crate::Document {
1356    type Error = FromError;
1357
1358    /// Create an apollo-encoder node from an apollo-parser one.
1359    ///
1360    /// # Errors
1361    /// This returns an error if the apollo-parser tree is not valid. The error
1362    /// doesn't have much context due to TryFrom API constraints: validate the parse tree before
1363    /// using TryFrom if granular errors are important to you.
1364    fn try_from(node: cst::Document) -> Result<Self, Self::Error> {
1365        let mut encoder_node = Self::new();
1366
1367        for definition in node.definitions() {
1368            match definition {
1369                cst::Definition::OperationDefinition(def) => {
1370                    encoder_node.operation(def.try_into()?)
1371                }
1372                cst::Definition::FragmentDefinition(def) => encoder_node.fragment(def.try_into()?),
1373                cst::Definition::DirectiveDefinition(def) => {
1374                    encoder_node.directive(def.try_into()?)
1375                }
1376                cst::Definition::SchemaDefinition(def) => encoder_node.schema(def.try_into()?),
1377                cst::Definition::ScalarTypeDefinition(def) => encoder_node.scalar(def.try_into()?),
1378                cst::Definition::ObjectTypeDefinition(def) => encoder_node.object(def.try_into()?),
1379                cst::Definition::InterfaceTypeDefinition(def) => {
1380                    encoder_node.interface(def.try_into()?)
1381                }
1382                cst::Definition::UnionTypeDefinition(def) => encoder_node.union(def.try_into()?),
1383                cst::Definition::EnumTypeDefinition(def) => encoder_node.enum_(def.try_into()?),
1384                cst::Definition::InputObjectTypeDefinition(def) => {
1385                    encoder_node.input_object(def.try_into()?)
1386                }
1387                cst::Definition::SchemaExtension(ext) => encoder_node.schema(ext.try_into()?),
1388                cst::Definition::ScalarTypeExtension(ext) => encoder_node.scalar(ext.try_into()?),
1389                cst::Definition::ObjectTypeExtension(ext) => encoder_node.object(ext.try_into()?),
1390                cst::Definition::InterfaceTypeExtension(ext) => {
1391                    encoder_node.interface(ext.try_into()?)
1392                }
1393                cst::Definition::UnionTypeExtension(ext) => encoder_node.union(ext.try_into()?),
1394                cst::Definition::EnumTypeExtension(ext) => encoder_node.enum_(ext.try_into()?),
1395                cst::Definition::InputObjectTypeExtension(ext) => {
1396                    encoder_node.input_object(ext.try_into()?)
1397                }
1398            }
1399        }
1400
1401        Ok(encoder_node)
1402    }
1403}
1404
1405#[cfg(test)]
1406mod tests {
1407    use crate::Document;
1408    use apollo_parser::Parser;
1409
1410    #[test]
1411    fn operation_definition() {
1412        let parser = Parser::new(
1413            r#"
1414query HeroForEpisode($ep: Episode!) {
1415  hero(episode: $ep) {
1416    name
1417    ... on Droid {
1418      primaryFunction
1419    }
1420    ... on Human {
1421      height
1422    }
1423  }
1424}
1425"#,
1426        );
1427        let cst = parser.parse();
1428        let doc = cst.document();
1429
1430        let encoder = Document::try_from(doc).unwrap();
1431        assert_eq!(
1432            encoder.to_string(),
1433            r#"
1434query HeroForEpisode($ep: Episode!) {
1435  hero(episode: $ep) {
1436    name
1437    ... on Droid {
1438      primaryFunction
1439    }
1440    ... on Human {
1441      height
1442    }
1443  }
1444}
1445"#
1446            .trim_start()
1447        );
1448    }
1449
1450    #[test]
1451    fn fragment_definition() {
1452        let parser = Parser::new(
1453            r#"
1454fragment FragmentDefinition on VeryRealType {
1455  id
1456  title
1457  text
1458}
1459"#,
1460        );
1461        let cst = parser.parse();
1462        let doc = cst.document();
1463
1464        let encoder = Document::try_from(doc).unwrap();
1465        assert_eq!(
1466            encoder.to_string(),
1467            r#"
1468fragment FragmentDefinition on VeryRealType {
1469  id
1470  title
1471  text
1472}
1473"#
1474            .trim_start()
1475        );
1476    }
1477
1478    #[test]
1479    fn directive_definition() {
1480        let parser = Parser::new(
1481            r#"
1482directive @withDeprecatedArgs(
1483  deprecatedArg: String @deprecated(reason: "Use `newArg`")
1484  newArg: String
1485) on FIELD
1486"#,
1487        );
1488        let cst = parser.parse();
1489        let doc = cst.document();
1490
1491        let encoder = Document::try_from(doc).unwrap();
1492        assert_eq!(encoder.to_string(), r#"
1493directive @withDeprecatedArgs(deprecatedArg: String @deprecated(reason: "Use `newArg`"), newArg: String) on FIELD
1494"#.trim_start());
1495    }
1496
1497    #[test]
1498    fn schema_definition() {
1499        let parser = Parser::new(
1500            r#"
1501schema {
1502  query: Query
1503  subscription: Subscription
1504}
1505extend schema {
1506  mutation: Mutation
1507}
1508"#,
1509        );
1510        let cst = parser.parse();
1511        let doc = cst.document();
1512
1513        let encoder = Document::try_from(doc).unwrap();
1514        assert_eq!(
1515            encoder.to_string(),
1516            r#"
1517schema {
1518  query: Query
1519  subscription: Subscription
1520}
1521extend schema {
1522  mutation: Mutation
1523}
1524"#
1525            .trim_start()
1526        );
1527    }
1528
1529    #[test]
1530    fn scalar_definition() {
1531        let parser = Parser::new(
1532            r#"
1533scalar Date
1534extend scalar Date @directive
1535"#,
1536        );
1537        let cst = parser.parse();
1538        let doc = cst.document();
1539
1540        let encoder = Document::try_from(doc).unwrap();
1541        assert_eq!(
1542            encoder.to_string(),
1543            r#"
1544scalar Date
1545extend scalar Date @directive
1546"#
1547            .trim_start()
1548        );
1549    }
1550
1551    #[test]
1552    fn object_type_definition() {
1553        let parser = Parser::new(
1554            r#"
1555type User implements X & Y
1556  @join__owner(graph: USERS)
1557  @join__type(graph: USERS, key: "email")
1558{
1559  email: String! @join__field(graph: USERS)
1560  id: String! @join__field(graph: USERS)
1561  name: String @join__field(graph: USERS)
1562  userProduct: UserProduct @join__field(graph: USERS)
1563}
1564"#,
1565        );
1566        let cst = parser.parse();
1567        let doc = cst.document();
1568
1569        let encoder = Document::try_from(doc).unwrap();
1570        assert_eq!(
1571            encoder.to_string(),
1572            r#"
1573type User implements X & Y @join__owner(graph: USERS) @join__type(graph: USERS, key: "email") {
1574  email: String! @join__field(graph: USERS)
1575  id: String! @join__field(graph: USERS)
1576  name: String @join__field(graph: USERS)
1577  userProduct: UserProduct @join__field(graph: USERS)
1578}
1579"#
1580            .trim_start()
1581        );
1582    }
1583
1584    #[test]
1585    fn interface_definition() {
1586        let parser = Parser::new(
1587            r#"
1588interface X {
1589  email: String!
1590}
1591interface Y {
1592  id: ID!
1593}
1594interface Z implements X & Y @inaccessible {}
1595"#,
1596        );
1597        let cst = parser.parse();
1598        let doc = cst.document();
1599
1600        let encoder = Document::try_from(doc).unwrap();
1601        assert_eq!(
1602            encoder.to_string(),
1603            r#"
1604interface X {
1605  email: String!
1606}
1607interface Y {
1608  id: ID!
1609}
1610interface Z implements X& Y @inaccessible {
1611}
1612"#
1613            .trim_start()
1614        );
1615    }
1616
1617    #[test]
1618    fn union_definition() {
1619        let parser = Parser::new(
1620            r#"
1621union UnionType = X | Y | Z
1622"#,
1623        );
1624        let cst = parser.parse();
1625        let doc = cst.document();
1626
1627        let encoder = Document::try_from(doc).unwrap();
1628        assert_eq!(
1629            encoder.to_string(),
1630            r#"
1631union UnionType = X | Y | Z
1632"#
1633            .trim_start()
1634        );
1635    }
1636
1637    #[test]
1638    fn enum_definition() {
1639        let parser = Parser::new(
1640            r#"
1641"Documentation for an enum"
1642enum EnumType {
1643  X
1644  "This is Y"
1645  Y
1646  Z @test()
1647}
1648"#,
1649        );
1650        let cst = parser.parse();
1651        let doc = cst.document();
1652
1653        let encoder = Document::try_from(doc).unwrap();
1654        assert_eq!(
1655            encoder.to_string(),
1656            r#"
1657"Documentation for an enum"
1658enum EnumType {
1659  X
1660  "This is Y"
1661  Y
1662  Z @test
1663}
1664"#
1665            .trim_start()
1666        );
1667    }
1668}