1use crate::ast;
65use crate::collections::HashMap;
66use crate::collections::IndexMap;
67use crate::collections::IndexSet;
68use crate::name;
69use crate::parser::FileId;
70use crate::parser::Parser;
71use crate::parser::SourceSpan;
72use crate::ty;
73use crate::validation::DiagnosticList;
74use crate::validation::Valid;
75use crate::validation::WithErrors;
76pub use crate::Name;
77use crate::Node;
78use std::path::Path;
79use std::sync::OnceLock;
80
81mod component;
82mod from_ast;
83mod serialize;
84pub(crate) mod validation;
85
86pub use self::component::Component;
87pub use self::component::ComponentName;
88pub use self::component::ComponentOrigin;
89pub use self::component::ExtensionId;
90pub use self::from_ast::SchemaBuilder;
91pub use crate::ast::Directive;
92pub use crate::ast::DirectiveDefinition;
93pub use crate::ast::DirectiveLocation;
94pub use crate::ast::EnumValueDefinition;
95pub use crate::ast::FieldDefinition;
96pub use crate::ast::InputValueDefinition;
97pub use crate::ast::NamedType;
98pub use crate::ast::Type;
99pub use crate::ast::Value;
100
101#[derive(Clone)]
103pub struct Schema {
104 pub sources: crate::parser::SourceMap,
108
109 pub schema_definition: Node<SchemaDefinition>,
111
112 pub directive_definitions: IndexMap<Name, Node<DirectiveDefinition>>,
114
115 pub types: IndexMap<NamedType, ExtendedType>,
128}
129
130#[derive(Debug, Clone, PartialEq, Eq, Default)]
133pub struct SchemaDefinition {
134 pub description: Option<Node<str>>,
135 pub directives: DirectiveList,
136
137 pub query: Option<ComponentName>,
139
140 pub mutation: Option<ComponentName>,
142
143 pub subscription: Option<ComponentName>,
145}
146
147#[derive(Clone, Eq, PartialEq, Hash, Default)]
157pub struct DirectiveList(pub Vec<Component<Directive>>);
158
159#[derive(Debug, Clone, PartialEq, Eq)]
163pub enum ExtendedType {
164 Scalar(Node<ScalarType>),
165 Object(Node<ObjectType>),
166 Interface(Node<InterfaceType>),
167 Union(Node<UnionType>),
168 Enum(Node<EnumType>),
169 InputObject(Node<InputObjectType>),
170}
171
172#[derive(Debug, Clone, PartialEq, Eq, Hash)]
175pub struct ScalarType {
176 pub description: Option<Node<str>>,
177 pub name: Name,
178 pub directives: DirectiveList,
179}
180
181#[derive(Debug, Clone, PartialEq, Eq)]
184pub struct ObjectType {
185 pub description: Option<Node<str>>,
186 pub name: Name,
187 pub implements_interfaces: IndexSet<ComponentName>,
188 pub directives: DirectiveList,
189
190 pub fields: IndexMap<Name, Component<FieldDefinition>>,
195}
196
197#[derive(Debug, Clone, PartialEq, Eq)]
198pub struct InterfaceType {
199 pub description: Option<Node<str>>,
200 pub name: Name,
201 pub implements_interfaces: IndexSet<ComponentName>,
202
203 pub directives: DirectiveList,
204
205 pub fields: IndexMap<Name, Component<FieldDefinition>>,
210}
211
212#[derive(Debug, Clone, PartialEq, Eq)]
215pub struct UnionType {
216 pub description: Option<Node<str>>,
217 pub name: Name,
218 pub directives: DirectiveList,
219
220 pub members: IndexSet<ComponentName>,
224}
225
226#[derive(Debug, Clone, PartialEq, Eq)]
229pub struct EnumType {
230 pub description: Option<Node<str>>,
231 pub name: Name,
232 pub directives: DirectiveList,
233 pub values: IndexMap<Name, Component<EnumValueDefinition>>,
234}
235
236#[derive(Debug, Clone, PartialEq, Eq)]
239pub struct InputObjectType {
240 pub description: Option<Node<str>>,
241 pub name: Name,
242 pub directives: DirectiveList,
243 pub fields: IndexMap<Name, Component<InputValueDefinition>>,
244}
245
246#[derive(Debug, Default, Clone, PartialEq, Eq)]
271pub struct Implementers {
272 pub objects: IndexSet<Name>,
274 pub interfaces: IndexSet<Name>,
276}
277
278#[derive(thiserror::Error, Debug, Clone)]
280pub(crate) enum BuildError {
281 #[error("a schema document must not contain {describe}")]
282 ExecutableDefinition { describe: &'static str },
283
284 #[error("must not have multiple `schema` definitions")]
285 SchemaDefinitionCollision {
286 previous_location: Option<SourceSpan>,
287 },
288
289 #[error("the directive `@{name}` is defined multiple times in the schema")]
290 DirectiveDefinitionCollision {
291 previous_location: Option<SourceSpan>,
292 name: Name,
293 },
294
295 #[error("the type `{name}` is defined multiple times in the schema")]
296 TypeDefinitionCollision {
297 previous_location: Option<SourceSpan>,
298 name: Name,
299 },
300
301 #[error("built-in scalar definitions must be omitted")]
302 BuiltInScalarTypeRedefinition,
303
304 #[error("schema extension without a schema definition")]
305 OrphanSchemaExtension,
306
307 #[error("type extension for undefined type `{name}`")]
308 OrphanTypeExtension { name: Name },
309
310 #[error("adding {describe_ext}, but `{name}` is {describe_def}")]
311 TypeExtensionKindMismatch {
312 name: Name,
313 describe_ext: &'static str,
314 def_location: Option<SourceSpan>,
315 describe_def: &'static str,
316 },
317
318 #[error("duplicate definitions for the `{operation_type}` root operation type")]
319 DuplicateRootOperation {
320 previous_location: Option<SourceSpan>,
321 operation_type: &'static str,
322 },
323
324 #[error(
325 "object type `{type_name}` implements interface `{name_at_previous_location}` \
326 more than once"
327 )]
328 DuplicateImplementsInterfaceInObject {
329 name_at_previous_location: Name,
330 type_name: Name,
331 },
332
333 #[error(
334 "interface type `{type_name}` implements interface `{name_at_previous_location}` \
335 more than once"
336 )]
337 DuplicateImplementsInterfaceInInterface {
338 name_at_previous_location: Name,
339 type_name: Name,
340 },
341
342 #[error(
343 "duplicate definitions for the `{name_at_previous_location}` \
344 field of object type `{type_name}`"
345 )]
346 ObjectFieldNameCollision {
347 name_at_previous_location: Name,
348 type_name: Name,
349 },
350
351 #[error(
352 "duplicate definitions for the `{name_at_previous_location}` \
353 field of interface type `{type_name}`"
354 )]
355 InterfaceFieldNameCollision {
356 name_at_previous_location: Name,
357 type_name: Name,
358 },
359
360 #[error(
361 "duplicate definitions for the `{name_at_previous_location}` \
362 value of enum type `{type_name}`"
363 )]
364 EnumValueNameCollision {
365 name_at_previous_location: Name,
366 type_name: Name,
367 },
368
369 #[error(
370 "duplicate definitions for the `{name_at_previous_location}` \
371 member of union type `{type_name}`"
372 )]
373 UnionMemberNameCollision {
374 name_at_previous_location: Name,
375 type_name: Name,
376 },
377
378 #[error(
379 "duplicate definitions for the `{name_at_previous_location}` \
380 field of input object type `{type_name}`"
381 )]
382 InputFieldNameCollision {
383 name_at_previous_location: Name,
384 type_name: Name,
385 },
386}
387
388#[derive(Debug, Clone, PartialEq, Eq)]
390pub enum FieldLookupError<'schema> {
391 NoSuchType,
392 NoSuchField(&'schema NamedType, &'schema ExtendedType),
393}
394
395impl Schema {
396 #[allow(clippy::new_without_default)] pub fn new() -> Self {
402 SchemaBuilder::new().build().unwrap()
403 }
404
405 #[allow(clippy::result_large_err)] pub fn parse(
411 source_text: impl Into<String>,
412 path: impl AsRef<Path>,
413 ) -> Result<Self, WithErrors<Self>> {
414 Parser::default().parse_schema(source_text, path)
415 }
416
417 #[allow(clippy::result_large_err)] pub fn parse_and_validate(
421 source_text: impl Into<String>,
422 path: impl AsRef<Path>,
423 ) -> Result<Valid<Self>, WithErrors<Self>> {
424 let mut builder = Schema::builder();
425 Parser::default().parse_into_schema_builder(source_text, path, &mut builder);
426 let (mut schema, mut errors) = builder.build_inner();
427 validation::validate_schema(&mut errors, &mut schema);
428 errors.into_valid_result(schema)
429 }
430
431 pub fn builder() -> SchemaBuilder {
440 SchemaBuilder::new()
441 }
442
443 #[allow(clippy::result_large_err)] pub fn validate(mut self) -> Result<Valid<Self>, WithErrors<Self>> {
445 let mut errors = DiagnosticList::new(self.sources.clone());
446 validation::validate_schema(&mut errors, &mut self);
447 errors.into_valid_result(self)
448 }
449
450 pub fn get_scalar(&self, name: &str) -> Option<&Node<ScalarType>> {
452 if let Some(ExtendedType::Scalar(ty)) = self.types.get(name) {
453 Some(ty)
454 } else {
455 None
456 }
457 }
458
459 pub fn get_object(&self, name: &str) -> Option<&Node<ObjectType>> {
461 if let Some(ExtendedType::Object(ty)) = self.types.get(name) {
462 Some(ty)
463 } else {
464 None
465 }
466 }
467
468 pub fn get_interface(&self, name: &str) -> Option<&Node<InterfaceType>> {
470 if let Some(ExtendedType::Interface(ty)) = self.types.get(name) {
471 Some(ty)
472 } else {
473 None
474 }
475 }
476
477 pub fn get_union(&self, name: &str) -> Option<&Node<UnionType>> {
479 if let Some(ExtendedType::Union(ty)) = self.types.get(name) {
480 Some(ty)
481 } else {
482 None
483 }
484 }
485
486 pub fn get_enum(&self, name: &str) -> Option<&Node<EnumType>> {
488 if let Some(ExtendedType::Enum(ty)) = self.types.get(name) {
489 Some(ty)
490 } else {
491 None
492 }
493 }
494
495 pub fn get_input_object(&self, name: &str) -> Option<&Node<InputObjectType>> {
497 if let Some(ExtendedType::InputObject(ty)) = self.types.get(name) {
498 Some(ty)
499 } else {
500 None
501 }
502 }
503
504 pub fn root_operation(&self, operation_type: ast::OperationType) -> Option<&NamedType> {
506 match operation_type {
507 ast::OperationType::Query => &self.schema_definition.query,
508 ast::OperationType::Mutation => &self.schema_definition.mutation,
509 ast::OperationType::Subscription => &self.schema_definition.subscription,
510 }
511 .as_ref()
512 .map(|component| &component.name)
513 }
514
515 pub fn type_field(
517 &self,
518 type_name: &str,
519 field_name: &str,
520 ) -> Result<&Component<FieldDefinition>, FieldLookupError<'_>> {
521 use ExtendedType::*;
522 let (ty_def_name, ty_def) = self
523 .types
524 .get_key_value(type_name)
525 .ok_or(FieldLookupError::NoSuchType)?;
526 let explicit_field = match ty_def {
527 Object(ty) => ty.fields.get(field_name),
528 Interface(ty) => ty.fields.get(field_name),
529 Scalar(_) | Union(_) | Enum(_) | InputObject(_) => None,
530 };
531 if let Some(def) = explicit_field {
532 return Ok(def);
533 }
534 let meta = MetaFieldDefinitions::get();
535 if field_name == "__typename" && matches!(ty_def, Object(_) | Interface(_) | Union(_)) {
536 return Ok(&meta.__typename);
538 }
539 if self
540 .schema_definition
541 .query
542 .as_ref()
543 .is_some_and(|query_type| query_type == type_name)
544 {
545 match field_name {
546 "__schema" => return Ok(&meta.__schema),
547 "__type" => return Ok(&meta.__type),
548 _ => {}
549 }
550 }
551 Err(FieldLookupError::NoSuchField(ty_def_name, ty_def))
552 }
553
554 pub fn implementers_map(&self) -> HashMap<Name, Implementers> {
563 let mut map = HashMap::<Name, Implementers>::default();
564 for (ty_name, ty) in &self.types {
565 match ty {
566 ExtendedType::Object(def) => {
567 for interface in &def.implements_interfaces {
568 map.entry(interface.name.clone())
569 .or_default()
570 .objects
571 .insert(ty_name.clone());
572 }
573 }
574 ExtendedType::Interface(def) => {
575 for interface in &def.implements_interfaces {
576 map.entry(interface.name.clone())
577 .or_default()
578 .interfaces
579 .insert(ty_name.clone());
580 }
581 }
582 ExtendedType::Scalar(_)
583 | ExtendedType::Union(_)
584 | ExtendedType::Enum(_)
585 | ExtendedType::InputObject(_) => (),
586 };
587 }
588 map
589 }
590
591 pub fn is_subtype(&self, abstract_type: &str, maybe_subtype: &str) -> bool {
596 self.types.get(abstract_type).is_some_and(|ty| match ty {
597 ExtendedType::Interface(_) => self.types.get(maybe_subtype).is_some_and(|ty2| {
598 match ty2 {
599 ExtendedType::Object(def) => &def.implements_interfaces,
600 ExtendedType::Interface(def) => &def.implements_interfaces,
601 ExtendedType::Scalar(_)
602 | ExtendedType::Union(_)
603 | ExtendedType::Enum(_)
604 | ExtendedType::InputObject(_) => return false,
605 }
606 .contains(abstract_type)
607 }),
608 ExtendedType::Union(def) => def.members.contains(maybe_subtype),
609 ExtendedType::Scalar(_)
610 | ExtendedType::Object(_)
611 | ExtendedType::Enum(_)
612 | ExtendedType::InputObject(_) => false,
613 })
614 }
615
616 pub fn is_input_type(&self, ty: &Type) -> bool {
620 match self.types.get(ty.inner_named_type()) {
621 Some(ExtendedType::Scalar(_))
622 | Some(ExtendedType::Enum(_))
623 | Some(ExtendedType::InputObject(_)) => true,
624 Some(ExtendedType::Object(_))
625 | Some(ExtendedType::Interface(_))
626 | Some(ExtendedType::Union(_))
627 | None => false,
628 }
629 }
630
631 pub fn is_output_type(&self, ty: &Type) -> bool {
635 match self.types.get(ty.inner_named_type()) {
636 Some(ExtendedType::Scalar(_))
637 | Some(ExtendedType::Object(_))
638 | Some(ExtendedType::Interface(_))
639 | Some(ExtendedType::Union(_))
640 | Some(ExtendedType::Enum(_)) => true,
641 Some(ExtendedType::InputObject(_)) | None => false,
642 }
643 }
644
645 serialize_method!();
646}
647
648impl SchemaDefinition {
649 pub fn iter_root_operations(
650 &self,
651 ) -> impl Iterator<Item = (ast::OperationType, &ComponentName)> {
652 [
653 (ast::OperationType::Query, &self.query),
654 (ast::OperationType::Mutation, &self.mutation),
655 (ast::OperationType::Subscription, &self.subscription),
656 ]
657 .into_iter()
658 .filter_map(|(ty, maybe_op)| maybe_op.as_ref().map(|op| (ty, op)))
659 }
660
661 pub fn extensions(&self) -> IndexSet<&ExtensionId> {
666 self.directives
667 .iter()
668 .flat_map(|dir| dir.origin.extension_id())
669 .chain(
670 self.query
671 .as_ref()
672 .and_then(|name| name.origin.extension_id()),
673 )
674 .chain(
675 self.mutation
676 .as_ref()
677 .and_then(|name| name.origin.extension_id()),
678 )
679 .chain(
680 self.subscription
681 .as_ref()
682 .and_then(|name| name.origin.extension_id()),
683 )
684 .collect()
685 }
686}
687
688impl ExtendedType {
689 pub fn name(&self) -> &Name {
690 match self {
691 Self::Scalar(def) => &def.name,
692 Self::Object(def) => &def.name,
693 Self::Interface(def) => &def.name,
694 Self::Union(def) => &def.name,
695 Self::Enum(def) => &def.name,
696 Self::InputObject(def) => &def.name,
697 }
698 }
699
700 pub fn location(&self) -> Option<SourceSpan> {
704 match self {
705 Self::Scalar(ty) => ty.location(),
706 Self::Object(ty) => ty.location(),
707 Self::Interface(ty) => ty.location(),
708 Self::Union(ty) => ty.location(),
709 Self::Enum(ty) => ty.location(),
710 Self::InputObject(ty) => ty.location(),
711 }
712 }
713
714 pub(crate) fn describe(&self) -> &'static str {
715 match self {
716 Self::Scalar(_) => "a scalar type",
717 Self::Object(_) => "an object type",
718 Self::Interface(_) => "an interface type",
719 Self::Union(_) => "a union type",
720 Self::Enum(_) => "an enum type",
721 Self::InputObject(_) => "an input object type",
722 }
723 }
724
725 pub fn is_scalar(&self) -> bool {
726 matches!(self, Self::Scalar(_))
727 }
728
729 pub fn is_object(&self) -> bool {
730 matches!(self, Self::Object(_))
731 }
732
733 pub fn is_interface(&self) -> bool {
734 matches!(self, Self::Interface(_))
735 }
736
737 pub fn is_union(&self) -> bool {
738 matches!(self, Self::Union(_))
739 }
740
741 pub fn is_enum(&self) -> bool {
742 matches!(self, Self::Enum(_))
743 }
744
745 pub fn is_input_object(&self) -> bool {
746 matches!(self, Self::InputObject(_))
747 }
748
749 pub fn as_scalar(&self) -> Option<&ScalarType> {
750 if let Self::Scalar(def) = self {
751 Some(def)
752 } else {
753 None
754 }
755 }
756
757 pub fn as_object(&self) -> Option<&ObjectType> {
758 if let Self::Object(def) = self {
759 Some(def)
760 } else {
761 None
762 }
763 }
764
765 pub fn as_interface(&self) -> Option<&InterfaceType> {
766 if let Self::Interface(def) = self {
767 Some(def)
768 } else {
769 None
770 }
771 }
772
773 pub fn as_union(&self) -> Option<&UnionType> {
774 if let Self::Union(def) = self {
775 Some(def)
776 } else {
777 None
778 }
779 }
780
781 pub fn as_enum(&self) -> Option<&EnumType> {
782 if let Self::Enum(def) = self {
783 Some(def)
784 } else {
785 None
786 }
787 }
788
789 pub fn as_input_object(&self) -> Option<&InputObjectType> {
790 if let Self::InputObject(def) = self {
791 Some(def)
792 } else {
793 None
794 }
795 }
796
797 pub fn is_leaf(&self) -> bool {
802 matches!(self, Self::Scalar(_) | Self::Enum(_))
803 }
804
805 pub fn is_input_type(&self) -> bool {
811 matches!(self, Self::Scalar(_) | Self::Enum(_) | Self::InputObject(_))
812 }
813
814 pub fn is_output_type(&self) -> bool {
820 matches!(
821 self,
822 Self::Scalar(_) | Self::Enum(_) | Self::Object(_) | Self::Interface(_) | Self::Union(_)
823 )
824 }
825
826 pub fn is_built_in(&self) -> bool {
828 match self {
829 Self::Scalar(ty) => ty.is_built_in(),
830 Self::Object(ty) => ty.is_built_in(),
831 Self::Interface(ty) => ty.is_built_in(),
832 Self::Union(ty) => ty.is_built_in(),
833 Self::Enum(ty) => ty.is_built_in(),
834 Self::InputObject(ty) => ty.is_built_in(),
835 }
836 }
837
838 pub fn directives(&self) -> &DirectiveList {
839 match self {
840 Self::Scalar(ty) => &ty.directives,
841 Self::Object(ty) => &ty.directives,
842 Self::Interface(ty) => &ty.directives,
843 Self::Union(ty) => &ty.directives,
844 Self::Enum(ty) => &ty.directives,
845 Self::InputObject(ty) => &ty.directives,
846 }
847 }
848
849 pub fn description(&self) -> Option<&Node<str>> {
850 match self {
851 Self::Scalar(ty) => ty.description.as_ref(),
852 Self::Object(ty) => ty.description.as_ref(),
853 Self::Interface(ty) => ty.description.as_ref(),
854 Self::Union(ty) => ty.description.as_ref(),
855 Self::Enum(ty) => ty.description.as_ref(),
856 Self::InputObject(ty) => ty.description.as_ref(),
857 }
858 }
859
860 serialize_method!();
861}
862
863impl ScalarType {
864 pub fn extensions(&self) -> IndexSet<&ExtensionId> {
869 self.directives
870 .iter()
871 .flat_map(|dir| dir.origin.extension_id())
872 .collect()
873 }
874
875 serialize_method!();
876}
877
878impl ObjectType {
879 pub fn extensions(&self) -> IndexSet<&ExtensionId> {
884 self.directives
885 .iter()
886 .flat_map(|dir| dir.origin.extension_id())
887 .chain(
888 self.implements_interfaces
889 .iter()
890 .flat_map(|component| component.origin.extension_id()),
891 )
892 .chain(
893 self.fields
894 .values()
895 .flat_map(|field| field.origin.extension_id()),
896 )
897 .collect()
898 }
899
900 serialize_method!();
901}
902
903impl InterfaceType {
904 pub fn extensions(&self) -> IndexSet<&ExtensionId> {
909 self.directives
910 .iter()
911 .flat_map(|dir| dir.origin.extension_id())
912 .chain(
913 self.implements_interfaces
914 .iter()
915 .flat_map(|component| component.origin.extension_id()),
916 )
917 .chain(
918 self.fields
919 .values()
920 .flat_map(|field| field.origin.extension_id()),
921 )
922 .collect()
923 }
924
925 serialize_method!();
926}
927
928impl UnionType {
929 pub fn extensions(&self) -> IndexSet<&ExtensionId> {
934 self.directives
935 .iter()
936 .flat_map(|dir| dir.origin.extension_id())
937 .chain(
938 self.members
939 .iter()
940 .flat_map(|component| component.origin.extension_id()),
941 )
942 .collect()
943 }
944
945 serialize_method!();
946}
947
948impl EnumType {
949 pub fn extensions(&self) -> IndexSet<&ExtensionId> {
954 self.directives
955 .iter()
956 .flat_map(|dir| dir.origin.extension_id())
957 .chain(
958 self.values
959 .values()
960 .flat_map(|value| value.origin.extension_id()),
961 )
962 .collect()
963 }
964
965 serialize_method!();
966}
967
968impl InputObjectType {
969 pub fn extensions(&self) -> IndexSet<&ExtensionId> {
974 self.directives
975 .iter()
976 .flat_map(|dir| dir.origin.extension_id())
977 .chain(
978 self.fields
979 .values()
980 .flat_map(|field| field.origin.extension_id()),
981 )
982 .collect()
983 }
984
985 serialize_method!();
986}
987
988impl DirectiveList {
989 pub const fn new() -> Self {
990 Self(Vec::new())
991 }
992
993 pub fn get_all<'def: 'name, 'name>(
998 &'def self,
999 name: &'name str,
1000 ) -> impl Iterator<Item = &'def Component<Directive>> + 'name {
1001 self.0.iter().filter(move |dir| dir.name == name)
1002 }
1003
1004 pub fn get(&self, name: &str) -> Option<&Component<Directive>> {
1009 self.get_all(name).next()
1010 }
1011
1012 pub fn has(&self, name: &str) -> bool {
1014 self.get(name).is_some()
1015 }
1016
1017 pub(crate) fn iter_ast(&self) -> impl Iterator<Item = &Node<ast::Directive>> {
1018 self.0.iter().map(|component| &component.node)
1019 }
1020
1021 pub fn push(&mut self, directive: impl Into<Component<Directive>>) {
1023 self.0.push(directive.into());
1024 }
1025
1026 serialize_method!();
1027}
1028
1029impl std::fmt::Debug for DirectiveList {
1030 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1031 self.0.fmt(f)
1032 }
1033}
1034
1035impl std::ops::Deref for DirectiveList {
1036 type Target = Vec<Component<Directive>>;
1037
1038 fn deref(&self) -> &Self::Target {
1039 &self.0
1040 }
1041}
1042
1043impl std::ops::DerefMut for DirectiveList {
1044 fn deref_mut(&mut self) -> &mut Self::Target {
1045 &mut self.0
1046 }
1047}
1048
1049impl IntoIterator for DirectiveList {
1050 type Item = Component<Directive>;
1051
1052 type IntoIter = std::vec::IntoIter<Component<Directive>>;
1053
1054 fn into_iter(self) -> Self::IntoIter {
1055 self.0.into_iter()
1056 }
1057}
1058
1059impl<'a> IntoIterator for &'a DirectiveList {
1060 type Item = &'a Component<Directive>;
1061
1062 type IntoIter = std::slice::Iter<'a, Component<Directive>>;
1063
1064 fn into_iter(self) -> Self::IntoIter {
1065 self.0.iter()
1066 }
1067}
1068
1069impl<'a> IntoIterator for &'a mut DirectiveList {
1070 type Item = &'a mut Component<Directive>;
1071
1072 type IntoIter = std::slice::IterMut<'a, Component<Directive>>;
1073
1074 fn into_iter(self) -> Self::IntoIter {
1075 self.0.iter_mut()
1076 }
1077}
1078
1079impl<D> FromIterator<D> for DirectiveList
1080where
1081 D: Into<Component<Directive>>,
1082{
1083 fn from_iter<T: IntoIterator<Item = D>>(iter: T) -> Self {
1084 Self(iter.into_iter().map(Into::into).collect())
1085 }
1086}
1087
1088impl Eq for Schema {}
1089
1090impl PartialEq for Schema {
1091 fn eq(&self, other: &Self) -> bool {
1092 let Self {
1093 sources: _, schema_definition,
1095 directive_definitions,
1096 types,
1097 } = self;
1098 *schema_definition == other.schema_definition
1099 && *directive_definitions == other.directive_definitions
1100 && *types == other.types
1101 }
1102}
1103
1104impl Implementers {
1105 pub fn iter(&self) -> impl Iterator<Item = &'_ Name> {
1109 self.objects.iter().chain(&self.interfaces)
1110 }
1111}
1112
1113impl From<Node<ScalarType>> for ExtendedType {
1114 fn from(ty: Node<ScalarType>) -> Self {
1115 Self::Scalar(ty)
1116 }
1117}
1118
1119impl From<Node<ObjectType>> for ExtendedType {
1120 fn from(ty: Node<ObjectType>) -> Self {
1121 Self::Object(ty)
1122 }
1123}
1124
1125impl From<Node<InterfaceType>> for ExtendedType {
1126 fn from(ty: Node<InterfaceType>) -> Self {
1127 Self::Interface(ty)
1128 }
1129}
1130
1131impl From<Node<UnionType>> for ExtendedType {
1132 fn from(ty: Node<UnionType>) -> Self {
1133 Self::Union(ty)
1134 }
1135}
1136
1137impl From<Node<EnumType>> for ExtendedType {
1138 fn from(ty: Node<EnumType>) -> Self {
1139 Self::Enum(ty)
1140 }
1141}
1142
1143impl From<Node<InputObjectType>> for ExtendedType {
1144 fn from(ty: Node<InputObjectType>) -> Self {
1145 Self::InputObject(ty)
1146 }
1147}
1148
1149impl From<ScalarType> for ExtendedType {
1150 fn from(ty: ScalarType) -> Self {
1151 Self::Scalar(ty.into())
1152 }
1153}
1154
1155impl From<ObjectType> for ExtendedType {
1156 fn from(ty: ObjectType) -> Self {
1157 Self::Object(ty.into())
1158 }
1159}
1160
1161impl From<InterfaceType> for ExtendedType {
1162 fn from(ty: InterfaceType) -> Self {
1163 Self::Interface(ty.into())
1164 }
1165}
1166
1167impl From<UnionType> for ExtendedType {
1168 fn from(ty: UnionType) -> Self {
1169 Self::Union(ty.into())
1170 }
1171}
1172
1173impl From<EnumType> for ExtendedType {
1174 fn from(ty: EnumType) -> Self {
1175 Self::Enum(ty.into())
1176 }
1177}
1178
1179impl From<InputObjectType> for ExtendedType {
1180 fn from(ty: InputObjectType) -> Self {
1181 Self::InputObject(ty.into())
1182 }
1183}
1184
1185impl std::fmt::Debug for Schema {
1186 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1187 let Self {
1188 sources,
1189 schema_definition,
1190 directive_definitions,
1191 types,
1192 } = self;
1193 f.debug_struct("Schema")
1194 .field("sources", sources)
1195 .field("schema_definition", schema_definition)
1196 .field(
1197 "directive_definitions",
1198 &DebugDirectiveDefinitions(directive_definitions),
1199 )
1200 .field("types", &DebugTypes(types))
1201 .finish()
1202 }
1203}
1204
1205struct DebugDirectiveDefinitions<'a>(&'a IndexMap<Name, Node<DirectiveDefinition>>);
1206
1207struct DebugTypes<'a>(&'a IndexMap<Name, ExtendedType>);
1208
1209impl std::fmt::Debug for DebugDirectiveDefinitions<'_> {
1210 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1211 let mut map = f.debug_map();
1212 for (name, def) in self.0 {
1213 if !def.is_built_in() {
1214 map.entry(name, def);
1215 } else {
1216 map.entry(name, &format_args!("built_in_directive!({name:?})"));
1217 }
1218 }
1219 map.finish()
1220 }
1221}
1222
1223impl std::fmt::Debug for DebugTypes<'_> {
1224 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1225 let mut map = f.debug_map();
1226 for (name, def) in self.0 {
1227 if !def.is_built_in() {
1228 map.entry(name, def);
1229 } else {
1230 map.entry(name, &format_args!("built_in_type!({name:?})"));
1231 }
1232 }
1233 map.finish()
1234 }
1235}
1236
1237struct MetaFieldDefinitions {
1238 __typename: Component<FieldDefinition>,
1239 __schema: Component<FieldDefinition>,
1240 __type: Component<FieldDefinition>,
1241}
1242
1243impl MetaFieldDefinitions {
1244 fn get() -> &'static Self {
1245 static DEFS: OnceLock<MetaFieldDefinitions> = OnceLock::new();
1246 DEFS.get_or_init(|| Self {
1247 __typename: Component::new(FieldDefinition {
1249 description: None,
1250 name: name!("__typename"),
1251 arguments: Vec::new(),
1252 ty: ty!(String!),
1253 directives: ast::DirectiveList::new(),
1254 }),
1255 __schema: Component::new(FieldDefinition {
1257 description: None,
1258 name: name!("__schema"),
1259 arguments: Vec::new(),
1260 ty: ty!(__Schema!),
1261 directives: ast::DirectiveList::new(),
1262 }),
1263 __type: Component::new(FieldDefinition {
1265 description: None,
1266 name: name!("__type"),
1267 arguments: vec![InputValueDefinition {
1268 description: None,
1269 name: name!("name"),
1270 ty: ty!(String!).into(),
1271 default_value: None,
1272 directives: ast::DirectiveList::new(),
1273 }
1274 .into()],
1275 ty: ty!(__Type),
1276 directives: ast::DirectiveList::new(),
1277 }),
1278 })
1279 }
1280}