1use crate::ast;
66use crate::collections::HashMap;
67use crate::collections::IndexMap;
68use crate::collections::IndexSet;
69use crate::name;
70use crate::parser::FileId;
71use crate::parser::Parser;
72use crate::parser::SourceSpan;
73use crate::ty;
74use crate::validation::DiagnosticList;
75use crate::validation::Valid;
76use crate::validation::WithErrors;
77pub use crate::Name;
78use crate::Node;
79use std::path::Path;
80use std::sync::OnceLock;
81
82mod from_ast;
83mod serialize;
84pub(crate) mod validation;
85
86pub use self::from_ast::SchemaBuilder;
87pub use crate::ast::Directive;
88pub use crate::ast::DirectiveDefinition;
89pub use crate::ast::DirectiveList;
90pub use crate::ast::DirectiveLocation;
91pub use crate::ast::EnumValueDefinition;
92pub use crate::ast::FieldDefinition;
93pub use crate::ast::InputValueDefinition;
94pub use crate::ast::NamedType;
95pub use crate::ast::Type;
96pub use crate::ast::Value;
97pub use crate::node::ExtensionId;
98
99#[derive(Clone)]
101pub struct Schema {
102 pub sources: crate::parser::SourceMap,
106
107 pub schema_definition: Node<SchemaDefinition>,
109
110 pub directive_definitions: IndexMap<Name, Node<DirectiveDefinition>>,
112
113 pub types: IndexMap<NamedType, ExtendedType>,
126
127 pub validate_default_values: bool,
133}
134
135#[derive(Debug, Clone, PartialEq, Eq, Default)]
138pub struct SchemaDefinition {
139 pub description: Option<Node<str>>,
140 pub directives: DirectiveList,
141
142 pub query: Option<Node<Name>>,
144
145 pub mutation: Option<Node<Name>>,
147
148 pub subscription: Option<Node<Name>>,
150}
151
152#[derive(Debug, Clone, PartialEq, Eq)]
156pub enum ExtendedType {
157 Scalar(Node<ScalarType>),
158 Object(Node<ObjectType>),
159 Interface(Node<InterfaceType>),
160 Union(Node<UnionType>),
161 Enum(Node<EnumType>),
162 InputObject(Node<InputObjectType>),
163}
164
165#[derive(Debug, Clone, PartialEq, Eq, Hash)]
168pub struct ScalarType {
169 pub description: Option<Node<str>>,
170 pub name: Name,
171 pub directives: DirectiveList,
172}
173
174#[derive(Debug, Clone, PartialEq, Eq)]
177pub struct ObjectType {
178 pub description: Option<Node<str>>,
179 pub name: Name,
180 pub implements_interfaces: IndexSet<Node<Name>>,
181 pub directives: DirectiveList,
182
183 pub fields: IndexMap<Name, Node<FieldDefinition>>,
188}
189
190#[derive(Debug, Clone, PartialEq, Eq)]
191pub struct InterfaceType {
192 pub description: Option<Node<str>>,
193 pub name: Name,
194 pub implements_interfaces: IndexSet<Node<Name>>,
195
196 pub directives: DirectiveList,
197
198 pub fields: IndexMap<Name, Node<FieldDefinition>>,
203}
204
205#[derive(Debug, Clone, PartialEq, Eq)]
208pub struct UnionType {
209 pub description: Option<Node<str>>,
210 pub name: Name,
211 pub directives: DirectiveList,
212
213 pub members: IndexSet<Node<Name>>,
217}
218
219#[derive(Debug, Clone, PartialEq, Eq)]
222pub struct EnumType {
223 pub description: Option<Node<str>>,
224 pub name: Name,
225 pub directives: DirectiveList,
226 pub values: IndexMap<Name, Node<EnumValueDefinition>>,
227}
228
229#[derive(Debug, Clone, PartialEq, Eq)]
232pub struct InputObjectType {
233 pub description: Option<Node<str>>,
234 pub name: Name,
235 pub directives: DirectiveList,
236 pub fields: IndexMap<Name, Node<InputValueDefinition>>,
237}
238
239#[derive(Debug, Default, Clone, PartialEq, Eq)]
264pub struct Implementers {
265 pub objects: IndexSet<Name>,
267 pub interfaces: IndexSet<Name>,
269}
270
271#[derive(thiserror::Error, Debug, Clone)]
273pub(crate) enum BuildError {
274 #[error("a schema document must not contain {describe}")]
275 ExecutableDefinition { describe: &'static str },
276
277 #[error("must not have multiple `schema` definitions")]
278 SchemaDefinitionCollision {
279 previous_location: Option<SourceSpan>,
280 },
281
282 #[error("the directive `@{name}` is defined multiple times in the schema")]
283 DirectiveDefinitionCollision {
284 previous_location: Option<SourceSpan>,
285 name: Name,
286 },
287
288 #[error("the type `{name}` is defined multiple times in the schema")]
289 TypeDefinitionCollision {
290 previous_location: Option<SourceSpan>,
291 name: Name,
292 },
293
294 #[error("built-in scalar definitions must be omitted")]
295 BuiltInScalarTypeRedefinition,
296
297 #[error("schema extension without a schema definition")]
298 OrphanSchemaExtension,
299
300 #[error("type extension for undefined type `{name}`")]
301 OrphanTypeExtension { name: Name },
302
303 #[error("adding {describe_ext}, but `{name}` is {describe_def}")]
304 TypeExtensionKindMismatch {
305 name: Name,
306 describe_ext: &'static str,
307 def_location: Option<SourceSpan>,
308 describe_def: &'static str,
309 },
310
311 #[error("duplicate definitions for the `{operation_type}` root operation type")]
312 DuplicateRootOperation {
313 previous_location: Option<SourceSpan>,
314 operation_type: &'static str,
315 },
316
317 #[error(
318 "object type `{type_name}` implements interface `{name_at_previous_location}` \
319 more than once"
320 )]
321 DuplicateImplementsInterfaceInObject {
322 name_at_previous_location: Name,
323 type_name: Name,
324 },
325
326 #[error(
327 "interface type `{type_name}` implements interface `{name_at_previous_location}` \
328 more than once"
329 )]
330 DuplicateImplementsInterfaceInInterface {
331 name_at_previous_location: Name,
332 type_name: Name,
333 },
334
335 #[error(
336 "duplicate definitions for the `{name_at_previous_location}` \
337 field of object type `{type_name}`"
338 )]
339 ObjectFieldNameCollision {
340 name_at_previous_location: Name,
341 type_name: Name,
342 },
343
344 #[error(
345 "duplicate definitions for the `{name_at_previous_location}` \
346 field of interface type `{type_name}`"
347 )]
348 InterfaceFieldNameCollision {
349 name_at_previous_location: Name,
350 type_name: Name,
351 },
352
353 #[error(
354 "duplicate definitions for the `{name_at_previous_location}` \
355 value of enum type `{type_name}`"
356 )]
357 EnumValueNameCollision {
358 name_at_previous_location: Name,
359 type_name: Name,
360 },
361
362 #[error(
363 "duplicate definitions for the `{name_at_previous_location}` \
364 member of union type `{type_name}`"
365 )]
366 UnionMemberNameCollision {
367 name_at_previous_location: Name,
368 type_name: Name,
369 },
370
371 #[error(
372 "duplicate definitions for the `{name_at_previous_location}` \
373 field of input object type `{type_name}`"
374 )]
375 InputFieldNameCollision {
376 name_at_previous_location: Name,
377 type_name: Name,
378 },
379}
380
381#[derive(Debug, Clone, PartialEq, Eq)]
383pub enum FieldLookupError<'schema> {
384 NoSuchType,
385 NoSuchField(&'schema NamedType, &'schema ExtendedType),
386}
387
388impl Schema {
389 #[allow(clippy::new_without_default)] pub fn new() -> Self {
395 SchemaBuilder::new().build().unwrap()
396 }
397
398 #[allow(clippy::result_large_err)] pub fn parse(
404 source_text: impl Into<String>,
405 path: impl AsRef<Path>,
406 ) -> Result<Self, WithErrors<Self>> {
407 Parser::default().parse_schema(source_text, path)
408 }
409
410 #[allow(clippy::result_large_err)] pub fn parse_and_validate(
414 source_text: impl Into<String>,
415 path: impl AsRef<Path>,
416 ) -> Result<Valid<Self>, WithErrors<Self>> {
417 let mut builder = Schema::builder();
418 Parser::default().parse_into_schema_builder(source_text, path, &mut builder);
419 let (mut schema, mut errors) = builder.build_inner();
420 validation::validate_schema(&mut errors, &mut schema);
421 errors.into_valid_result(schema)
422 }
423
424 pub fn builder() -> SchemaBuilder {
433 SchemaBuilder::new()
434 }
435
436 #[allow(clippy::result_large_err)] pub fn validate(mut self) -> Result<Valid<Self>, WithErrors<Self>> {
438 let mut errors = DiagnosticList::new(self.sources.clone());
439 validation::validate_schema(&mut errors, &mut self);
440 errors.into_valid_result(self)
441 }
442
443 pub fn get_scalar(&self, name: &str) -> Option<&Node<ScalarType>> {
445 if let Some(ExtendedType::Scalar(ty)) = self.types.get(name) {
446 Some(ty)
447 } else {
448 None
449 }
450 }
451
452 pub fn get_object(&self, name: &str) -> Option<&Node<ObjectType>> {
454 if let Some(ExtendedType::Object(ty)) = self.types.get(name) {
455 Some(ty)
456 } else {
457 None
458 }
459 }
460
461 pub fn get_interface(&self, name: &str) -> Option<&Node<InterfaceType>> {
463 if let Some(ExtendedType::Interface(ty)) = self.types.get(name) {
464 Some(ty)
465 } else {
466 None
467 }
468 }
469
470 pub fn get_union(&self, name: &str) -> Option<&Node<UnionType>> {
472 if let Some(ExtendedType::Union(ty)) = self.types.get(name) {
473 Some(ty)
474 } else {
475 None
476 }
477 }
478
479 pub fn get_enum(&self, name: &str) -> Option<&Node<EnumType>> {
481 if let Some(ExtendedType::Enum(ty)) = self.types.get(name) {
482 Some(ty)
483 } else {
484 None
485 }
486 }
487
488 pub fn get_input_object(&self, name: &str) -> Option<&Node<InputObjectType>> {
490 if let Some(ExtendedType::InputObject(ty)) = self.types.get(name) {
491 Some(ty)
492 } else {
493 None
494 }
495 }
496
497 pub fn root_operation(&self, operation_type: ast::OperationType) -> Option<&NamedType> {
499 match operation_type {
500 ast::OperationType::Query => &self.schema_definition.query,
501 ast::OperationType::Mutation => &self.schema_definition.mutation,
502 ast::OperationType::Subscription => &self.schema_definition.subscription,
503 }
504 .as_ref()
505 .map(|component| component.as_ref())
506 }
507
508 pub fn type_field(
510 &self,
511 type_name: &str,
512 field_name: &str,
513 ) -> Result<&Node<FieldDefinition>, FieldLookupError<'_>> {
514 use ExtendedType::*;
515 let (ty_def_name, ty_def) = self
516 .types
517 .get_key_value(type_name)
518 .ok_or(FieldLookupError::NoSuchType)?;
519 let explicit_field = match ty_def {
520 Object(ty) => ty.fields.get(field_name),
521 Interface(ty) => ty.fields.get(field_name),
522 Scalar(_) | Union(_) | Enum(_) | InputObject(_) => None,
523 };
524 if let Some(def) = explicit_field {
525 return Ok(def);
526 }
527 let meta = MetaFieldDefinitions::get();
528 if field_name == "__typename" && matches!(ty_def, Object(_) | Interface(_) | Union(_)) {
529 return Ok(&meta.__typename);
531 }
532 if self
533 .schema_definition
534 .query
535 .as_ref()
536 .is_some_and(|query_type| query_type == type_name)
537 {
538 match field_name {
539 "__schema" => return Ok(&meta.__schema),
540 "__type" => return Ok(&meta.__type),
541 _ => {}
542 }
543 }
544 Err(FieldLookupError::NoSuchField(ty_def_name, ty_def))
545 }
546
547 pub fn implementers_map(&self) -> HashMap<Name, Implementers> {
556 let mut map = HashMap::<Name, Implementers>::default();
557 for (ty_name, ty) in &self.types {
558 match ty {
559 ExtendedType::Object(def) => {
560 for interface in &def.implements_interfaces {
561 map.entry(interface.as_ref().clone())
562 .or_default()
563 .objects
564 .insert(ty_name.clone());
565 }
566 }
567 ExtendedType::Interface(def) => {
568 for interface in &def.implements_interfaces {
569 map.entry(interface.as_ref().clone())
570 .or_default()
571 .interfaces
572 .insert(ty_name.clone());
573 }
574 }
575 ExtendedType::Scalar(_)
576 | ExtendedType::Union(_)
577 | ExtendedType::Enum(_)
578 | ExtendedType::InputObject(_) => (),
579 };
580 }
581 map
582 }
583
584 pub fn is_subtype(&self, abstract_type: &str, maybe_subtype: &str) -> bool {
589 self.types.get(abstract_type).is_some_and(|ty| match ty {
590 ExtendedType::Interface(_) => self.types.get(maybe_subtype).is_some_and(|ty2| {
591 match ty2 {
592 ExtendedType::Object(def) => &def.implements_interfaces,
593 ExtendedType::Interface(def) => &def.implements_interfaces,
594 ExtendedType::Scalar(_)
595 | ExtendedType::Union(_)
596 | ExtendedType::Enum(_)
597 | ExtendedType::InputObject(_) => return false,
598 }
599 .contains(abstract_type)
600 }),
601 ExtendedType::Union(def) => def.members.contains(maybe_subtype),
602 ExtendedType::Scalar(_)
603 | ExtendedType::Object(_)
604 | ExtendedType::Enum(_)
605 | ExtendedType::InputObject(_) => false,
606 })
607 }
608
609 pub fn is_input_type(&self, ty: &Type) -> bool {
613 match self.types.get(ty.inner_named_type()) {
614 Some(ExtendedType::Scalar(_))
615 | Some(ExtendedType::Enum(_))
616 | Some(ExtendedType::InputObject(_)) => true,
617 Some(ExtendedType::Object(_))
618 | Some(ExtendedType::Interface(_))
619 | Some(ExtendedType::Union(_))
620 | None => false,
621 }
622 }
623
624 pub fn is_output_type(&self, ty: &Type) -> bool {
628 match self.types.get(ty.inner_named_type()) {
629 Some(ExtendedType::Scalar(_))
630 | Some(ExtendedType::Object(_))
631 | Some(ExtendedType::Interface(_))
632 | Some(ExtendedType::Union(_))
633 | Some(ExtendedType::Enum(_)) => true,
634 Some(ExtendedType::InputObject(_)) | None => false,
635 }
636 }
637
638 serialize_method!();
639}
640
641impl SchemaDefinition {
642 pub fn iter_root_operations(&self) -> impl Iterator<Item = (ast::OperationType, &Node<Name>)> {
643 [
644 (ast::OperationType::Query, &self.query),
645 (ast::OperationType::Mutation, &self.mutation),
646 (ast::OperationType::Subscription, &self.subscription),
647 ]
648 .into_iter()
649 .filter_map(|(ty, maybe_op)| maybe_op.as_ref().map(|op| (ty, op)))
650 }
651
652 pub fn iter_extension_ids(&self) -> impl Iterator<Item = Option<&ExtensionId>> {
657 self.directives
658 .iter()
659 .map(|dir| dir.extension_id())
660 .chain(self.query.iter().map(|name| name.extension_id()))
661 .chain(self.mutation.iter().map(|name| name.extension_id()))
662 .chain(self.subscription.iter().map(|name| name.extension_id()))
663 }
664
665 pub fn extensions(&self) -> IndexSet<&ExtensionId> {
670 self.iter_extension_ids().flatten().collect()
671 }
672}
673
674impl ExtendedType {
675 pub fn name(&self) -> &Name {
676 match self {
677 Self::Scalar(def) => &def.name,
678 Self::Object(def) => &def.name,
679 Self::Interface(def) => &def.name,
680 Self::Union(def) => &def.name,
681 Self::Enum(def) => &def.name,
682 Self::InputObject(def) => &def.name,
683 }
684 }
685
686 pub fn location(&self) -> Option<SourceSpan> {
690 match self {
691 Self::Scalar(ty) => ty.location(),
692 Self::Object(ty) => ty.location(),
693 Self::Interface(ty) => ty.location(),
694 Self::Union(ty) => ty.location(),
695 Self::Enum(ty) => ty.location(),
696 Self::InputObject(ty) => ty.location(),
697 }
698 }
699
700 pub(crate) fn describe(&self) -> &'static str {
701 match self {
702 Self::Scalar(_) => "a scalar type",
703 Self::Object(_) => "an object type",
704 Self::Interface(_) => "an interface type",
705 Self::Union(_) => "a union type",
706 Self::Enum(_) => "an enum type",
707 Self::InputObject(_) => "an input object type",
708 }
709 }
710
711 pub fn is_scalar(&self) -> bool {
712 matches!(self, Self::Scalar(_))
713 }
714
715 pub fn is_object(&self) -> bool {
716 matches!(self, Self::Object(_))
717 }
718
719 pub fn is_interface(&self) -> bool {
720 matches!(self, Self::Interface(_))
721 }
722
723 pub fn is_union(&self) -> bool {
724 matches!(self, Self::Union(_))
725 }
726
727 pub fn is_enum(&self) -> bool {
728 matches!(self, Self::Enum(_))
729 }
730
731 pub fn is_input_object(&self) -> bool {
732 matches!(self, Self::InputObject(_))
733 }
734
735 pub fn as_scalar(&self) -> Option<&ScalarType> {
736 if let Self::Scalar(def) = self {
737 Some(def)
738 } else {
739 None
740 }
741 }
742
743 pub fn as_object(&self) -> Option<&ObjectType> {
744 if let Self::Object(def) = self {
745 Some(def)
746 } else {
747 None
748 }
749 }
750
751 pub fn as_interface(&self) -> Option<&InterfaceType> {
752 if let Self::Interface(def) = self {
753 Some(def)
754 } else {
755 None
756 }
757 }
758
759 pub fn as_union(&self) -> Option<&UnionType> {
760 if let Self::Union(def) = self {
761 Some(def)
762 } else {
763 None
764 }
765 }
766
767 pub fn as_enum(&self) -> Option<&EnumType> {
768 if let Self::Enum(def) = self {
769 Some(def)
770 } else {
771 None
772 }
773 }
774
775 pub fn as_input_object(&self) -> Option<&InputObjectType> {
776 if let Self::InputObject(def) = self {
777 Some(def)
778 } else {
779 None
780 }
781 }
782
783 pub fn is_leaf(&self) -> bool {
788 matches!(self, Self::Scalar(_) | Self::Enum(_))
789 }
790
791 pub fn is_input_type(&self) -> bool {
797 matches!(self, Self::Scalar(_) | Self::Enum(_) | Self::InputObject(_))
798 }
799
800 pub fn is_output_type(&self) -> bool {
806 matches!(
807 self,
808 Self::Scalar(_) | Self::Enum(_) | Self::Object(_) | Self::Interface(_) | Self::Union(_)
809 )
810 }
811
812 pub fn is_built_in(&self) -> bool {
814 match self {
815 Self::Scalar(ty) => ty.is_built_in(),
816 Self::Object(ty) => ty.is_built_in(),
817 Self::Interface(ty) => ty.is_built_in(),
818 Self::Union(ty) => ty.is_built_in(),
819 Self::Enum(ty) => ty.is_built_in(),
820 Self::InputObject(ty) => ty.is_built_in(),
821 }
822 }
823
824 pub fn directives(&self) -> &DirectiveList {
825 match self {
826 Self::Scalar(ty) => &ty.directives,
827 Self::Object(ty) => &ty.directives,
828 Self::Interface(ty) => &ty.directives,
829 Self::Union(ty) => &ty.directives,
830 Self::Enum(ty) => &ty.directives,
831 Self::InputObject(ty) => &ty.directives,
832 }
833 }
834
835 pub fn description(&self) -> Option<&Node<str>> {
836 match self {
837 Self::Scalar(ty) => ty.description.as_ref(),
838 Self::Object(ty) => ty.description.as_ref(),
839 Self::Interface(ty) => ty.description.as_ref(),
840 Self::Union(ty) => ty.description.as_ref(),
841 Self::Enum(ty) => ty.description.as_ref(),
842 Self::InputObject(ty) => ty.description.as_ref(),
843 }
844 }
845
846 pub fn iter_extension_ids(&self) -> impl Iterator<Item = Option<&ExtensionId>> {
851 match self {
852 Self::Scalar(ty) => Box::new(ty.iter_extension_ids()) as Box<dyn Iterator<Item = _>>,
853 Self::Object(ty) => Box::new(ty.iter_extension_ids()),
854 Self::Interface(ty) => Box::new(ty.iter_extension_ids()),
855 Self::Union(ty) => Box::new(ty.iter_extension_ids()),
856 Self::Enum(ty) => Box::new(ty.iter_extension_ids()),
857 Self::InputObject(ty) => Box::new(ty.iter_extension_ids()),
858 }
859 }
860
861 pub fn extensions(&self) -> IndexSet<&ExtensionId> {
866 self.iter_extension_ids().flatten().collect()
867 }
868
869 serialize_method!();
870}
871
872impl ScalarType {
873 pub fn iter_extension_ids(&self) -> impl Iterator<Item = Option<&ExtensionId>> {
878 self.directives.iter().map(|dir| dir.extension_id())
879 }
880
881 pub fn extensions(&self) -> IndexSet<&ExtensionId> {
886 self.iter_extension_ids().flatten().collect()
887 }
888
889 serialize_method!();
890}
891
892impl ObjectType {
893 pub fn iter_extension_ids(&self) -> impl Iterator<Item = Option<&ExtensionId>> {
898 self.directives
899 .iter()
900 .map(|dir| dir.extension_id())
901 .chain(
902 self.implements_interfaces
903 .iter()
904 .map(|component| component.extension_id()),
905 )
906 .chain(self.fields.values().map(|field| field.extension_id()))
907 }
908
909 pub fn extensions(&self) -> IndexSet<&ExtensionId> {
914 self.iter_extension_ids().flatten().collect()
915 }
916
917 serialize_method!();
918}
919
920impl InterfaceType {
921 pub fn iter_extension_ids(&self) -> impl Iterator<Item = Option<&ExtensionId>> {
926 self.directives
927 .iter()
928 .map(|dir| dir.extension_id())
929 .chain(
930 self.implements_interfaces
931 .iter()
932 .map(|component| component.extension_id()),
933 )
934 .chain(self.fields.values().map(|field| field.extension_id()))
935 }
936
937 pub fn extensions(&self) -> IndexSet<&ExtensionId> {
942 self.iter_extension_ids().flatten().collect()
943 }
944
945 serialize_method!();
946}
947
948impl UnionType {
949 pub fn iter_extension_ids(&self) -> impl Iterator<Item = Option<&ExtensionId>> {
954 self.directives.iter().map(|dir| dir.extension_id()).chain(
955 self.members
956 .iter()
957 .map(|component| component.extension_id()),
958 )
959 }
960
961 pub fn extensions(&self) -> IndexSet<&ExtensionId> {
966 self.iter_extension_ids().flatten().collect()
967 }
968
969 serialize_method!();
970}
971
972impl EnumType {
973 pub fn iter_extension_ids(&self) -> impl Iterator<Item = Option<&ExtensionId>> {
978 self.directives
979 .iter()
980 .map(|dir| dir.extension_id())
981 .chain(self.values.values().map(|value| value.extension_id()))
982 }
983
984 pub fn extensions(&self) -> IndexSet<&ExtensionId> {
989 self.iter_extension_ids().flatten().collect()
990 }
991
992 serialize_method!();
993}
994
995impl InputObjectType {
996 pub fn is_one_of(&self) -> bool {
998 self.directives.get("oneOf").is_some()
999 }
1000
1001 pub fn iter_extension_ids(&self) -> impl Iterator<Item = Option<&ExtensionId>> {
1006 self.directives
1007 .iter()
1008 .map(|dir| dir.extension_id())
1009 .chain(self.fields.values().map(|field| field.extension_id()))
1010 }
1011
1012 pub fn extensions(&self) -> IndexSet<&ExtensionId> {
1017 self.iter_extension_ids().flatten().collect()
1018 }
1019
1020 serialize_method!();
1021}
1022
1023impl Eq for Schema {}
1024
1025impl PartialEq for Schema {
1026 fn eq(&self, other: &Self) -> bool {
1027 let Self {
1028 sources: _, validate_default_values: _, schema_definition,
1031 directive_definitions,
1032 types,
1033 } = self;
1034 *schema_definition == other.schema_definition
1035 && *directive_definitions == other.directive_definitions
1036 && *types == other.types
1037 }
1038}
1039
1040impl Implementers {
1041 pub fn iter(&self) -> impl Iterator<Item = &'_ Name> {
1045 self.objects.iter().chain(&self.interfaces)
1046 }
1047}
1048
1049impl From<Node<ScalarType>> for ExtendedType {
1050 fn from(ty: Node<ScalarType>) -> Self {
1051 Self::Scalar(ty)
1052 }
1053}
1054
1055impl From<Node<ObjectType>> for ExtendedType {
1056 fn from(ty: Node<ObjectType>) -> Self {
1057 Self::Object(ty)
1058 }
1059}
1060
1061impl From<Node<InterfaceType>> for ExtendedType {
1062 fn from(ty: Node<InterfaceType>) -> Self {
1063 Self::Interface(ty)
1064 }
1065}
1066
1067impl From<Node<UnionType>> for ExtendedType {
1068 fn from(ty: Node<UnionType>) -> Self {
1069 Self::Union(ty)
1070 }
1071}
1072
1073impl From<Node<EnumType>> for ExtendedType {
1074 fn from(ty: Node<EnumType>) -> Self {
1075 Self::Enum(ty)
1076 }
1077}
1078
1079impl From<Node<InputObjectType>> for ExtendedType {
1080 fn from(ty: Node<InputObjectType>) -> Self {
1081 Self::InputObject(ty)
1082 }
1083}
1084
1085impl From<ScalarType> for ExtendedType {
1086 fn from(ty: ScalarType) -> Self {
1087 Self::Scalar(ty.into())
1088 }
1089}
1090
1091impl From<ObjectType> for ExtendedType {
1092 fn from(ty: ObjectType) -> Self {
1093 Self::Object(ty.into())
1094 }
1095}
1096
1097impl From<InterfaceType> for ExtendedType {
1098 fn from(ty: InterfaceType) -> Self {
1099 Self::Interface(ty.into())
1100 }
1101}
1102
1103impl From<UnionType> for ExtendedType {
1104 fn from(ty: UnionType) -> Self {
1105 Self::Union(ty.into())
1106 }
1107}
1108
1109impl From<EnumType> for ExtendedType {
1110 fn from(ty: EnumType) -> Self {
1111 Self::Enum(ty.into())
1112 }
1113}
1114
1115impl From<InputObjectType> for ExtendedType {
1116 fn from(ty: InputObjectType) -> Self {
1117 Self::InputObject(ty.into())
1118 }
1119}
1120
1121impl std::fmt::Debug for Schema {
1122 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1123 let Self {
1124 sources,
1125 schema_definition,
1126 directive_definitions,
1127 types,
1128 validate_default_values: _,
1129 } = self;
1130 f.debug_struct("Schema")
1131 .field("sources", sources)
1132 .field("schema_definition", schema_definition)
1133 .field(
1134 "directive_definitions",
1135 &DebugDirectiveDefinitions(directive_definitions),
1136 )
1137 .field("types", &DebugTypes(types))
1138 .finish()
1139 }
1140}
1141
1142struct DebugDirectiveDefinitions<'a>(&'a IndexMap<Name, Node<DirectiveDefinition>>);
1143
1144struct DebugTypes<'a>(&'a IndexMap<Name, ExtendedType>);
1145
1146impl std::fmt::Debug for DebugDirectiveDefinitions<'_> {
1147 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1148 let mut map = f.debug_map();
1149 for (name, def) in self.0 {
1150 if !def.is_built_in() {
1151 map.entry(name, def);
1152 } else {
1153 map.entry(name, &format_args!("built_in_directive!({name:?})"));
1154 }
1155 }
1156 map.finish()
1157 }
1158}
1159
1160impl std::fmt::Debug for DebugTypes<'_> {
1161 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1162 let mut map = f.debug_map();
1163 for (name, def) in self.0 {
1164 if !def.is_built_in() {
1165 map.entry(name, def);
1166 } else {
1167 map.entry(name, &format_args!("built_in_type!({name:?})"));
1168 }
1169 }
1170 map.finish()
1171 }
1172}
1173
1174struct MetaFieldDefinitions {
1175 __typename: Node<FieldDefinition>,
1176 __schema: Node<FieldDefinition>,
1177 __type: Node<FieldDefinition>,
1178}
1179
1180impl MetaFieldDefinitions {
1181 fn get() -> &'static Self {
1182 static DEFS: OnceLock<MetaFieldDefinitions> = OnceLock::new();
1183 DEFS.get_or_init(|| Self {
1184 __typename: Node::new(FieldDefinition {
1186 description: None,
1187 name: name!("__typename"),
1188 arguments: Vec::new(),
1189 ty: ty!(String!),
1190 directives: ast::DirectiveList::new(),
1191 }),
1192 __schema: Node::new(FieldDefinition {
1194 description: None,
1195 name: name!("__schema"),
1196 arguments: Vec::new(),
1197 ty: ty!(__Schema!),
1198 directives: ast::DirectiveList::new(),
1199 }),
1200 __type: Node::new(FieldDefinition {
1202 description: None,
1203 name: name!("__type"),
1204 arguments: vec![InputValueDefinition {
1205 description: None,
1206 name: name!("name"),
1207 ty: ty!(String!).into(),
1208 default_value: None,
1209 directives: ast::DirectiveList::new(),
1210 }
1211 .into()],
1212 ty: ty!(__Type),
1213 directives: ast::DirectiveList::new(),
1214 }),
1215 })
1216 }
1217}