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 iter_origins(&self) -> impl Iterator<Item = &ComponentOrigin> {
666 self.directives
667 .iter()
668 .map(|dir| &dir.origin)
669 .chain(self.query.iter().map(|name| &name.origin))
670 .chain(self.mutation.iter().map(|name| &name.origin))
671 .chain(self.subscription.iter().map(|name| &name.origin))
672 }
673
674 pub fn extensions(&self) -> IndexSet<&ExtensionId> {
679 self.iter_origins()
680 .filter_map(|origin| origin.extension_id())
681 .collect()
682 }
683}
684
685impl ExtendedType {
686 pub fn name(&self) -> &Name {
687 match self {
688 Self::Scalar(def) => &def.name,
689 Self::Object(def) => &def.name,
690 Self::Interface(def) => &def.name,
691 Self::Union(def) => &def.name,
692 Self::Enum(def) => &def.name,
693 Self::InputObject(def) => &def.name,
694 }
695 }
696
697 pub fn location(&self) -> Option<SourceSpan> {
701 match self {
702 Self::Scalar(ty) => ty.location(),
703 Self::Object(ty) => ty.location(),
704 Self::Interface(ty) => ty.location(),
705 Self::Union(ty) => ty.location(),
706 Self::Enum(ty) => ty.location(),
707 Self::InputObject(ty) => ty.location(),
708 }
709 }
710
711 pub(crate) fn describe(&self) -> &'static str {
712 match self {
713 Self::Scalar(_) => "a scalar type",
714 Self::Object(_) => "an object type",
715 Self::Interface(_) => "an interface type",
716 Self::Union(_) => "a union type",
717 Self::Enum(_) => "an enum type",
718 Self::InputObject(_) => "an input object type",
719 }
720 }
721
722 pub fn is_scalar(&self) -> bool {
723 matches!(self, Self::Scalar(_))
724 }
725
726 pub fn is_object(&self) -> bool {
727 matches!(self, Self::Object(_))
728 }
729
730 pub fn is_interface(&self) -> bool {
731 matches!(self, Self::Interface(_))
732 }
733
734 pub fn is_union(&self) -> bool {
735 matches!(self, Self::Union(_))
736 }
737
738 pub fn is_enum(&self) -> bool {
739 matches!(self, Self::Enum(_))
740 }
741
742 pub fn is_input_object(&self) -> bool {
743 matches!(self, Self::InputObject(_))
744 }
745
746 pub fn as_scalar(&self) -> Option<&ScalarType> {
747 if let Self::Scalar(def) = self {
748 Some(def)
749 } else {
750 None
751 }
752 }
753
754 pub fn as_object(&self) -> Option<&ObjectType> {
755 if let Self::Object(def) = self {
756 Some(def)
757 } else {
758 None
759 }
760 }
761
762 pub fn as_interface(&self) -> Option<&InterfaceType> {
763 if let Self::Interface(def) = self {
764 Some(def)
765 } else {
766 None
767 }
768 }
769
770 pub fn as_union(&self) -> Option<&UnionType> {
771 if let Self::Union(def) = self {
772 Some(def)
773 } else {
774 None
775 }
776 }
777
778 pub fn as_enum(&self) -> Option<&EnumType> {
779 if let Self::Enum(def) = self {
780 Some(def)
781 } else {
782 None
783 }
784 }
785
786 pub fn as_input_object(&self) -> Option<&InputObjectType> {
787 if let Self::InputObject(def) = self {
788 Some(def)
789 } else {
790 None
791 }
792 }
793
794 pub fn is_leaf(&self) -> bool {
799 matches!(self, Self::Scalar(_) | Self::Enum(_))
800 }
801
802 pub fn is_input_type(&self) -> bool {
808 matches!(self, Self::Scalar(_) | Self::Enum(_) | Self::InputObject(_))
809 }
810
811 pub fn is_output_type(&self) -> bool {
817 matches!(
818 self,
819 Self::Scalar(_) | Self::Enum(_) | Self::Object(_) | Self::Interface(_) | Self::Union(_)
820 )
821 }
822
823 pub fn is_built_in(&self) -> bool {
825 match self {
826 Self::Scalar(ty) => ty.is_built_in(),
827 Self::Object(ty) => ty.is_built_in(),
828 Self::Interface(ty) => ty.is_built_in(),
829 Self::Union(ty) => ty.is_built_in(),
830 Self::Enum(ty) => ty.is_built_in(),
831 Self::InputObject(ty) => ty.is_built_in(),
832 }
833 }
834
835 pub fn directives(&self) -> &DirectiveList {
836 match self {
837 Self::Scalar(ty) => &ty.directives,
838 Self::Object(ty) => &ty.directives,
839 Self::Interface(ty) => &ty.directives,
840 Self::Union(ty) => &ty.directives,
841 Self::Enum(ty) => &ty.directives,
842 Self::InputObject(ty) => &ty.directives,
843 }
844 }
845
846 pub fn description(&self) -> Option<&Node<str>> {
847 match self {
848 Self::Scalar(ty) => ty.description.as_ref(),
849 Self::Object(ty) => ty.description.as_ref(),
850 Self::Interface(ty) => ty.description.as_ref(),
851 Self::Union(ty) => ty.description.as_ref(),
852 Self::Enum(ty) => ty.description.as_ref(),
853 Self::InputObject(ty) => ty.description.as_ref(),
854 }
855 }
856
857 pub fn iter_origins(&self) -> impl Iterator<Item = &ComponentOrigin> {
862 match self {
863 Self::Scalar(ty) => Box::new(ty.iter_origins()) as Box<dyn Iterator<Item = _>>,
864 Self::Object(ty) => Box::new(ty.iter_origins()),
865 Self::Interface(ty) => Box::new(ty.iter_origins()),
866 Self::Union(ty) => Box::new(ty.iter_origins()),
867 Self::Enum(ty) => Box::new(ty.iter_origins()),
868 Self::InputObject(ty) => Box::new(ty.iter_origins()),
869 }
870 }
871
872 pub fn extensions(&self) -> IndexSet<&ExtensionId> {
877 self.iter_origins()
878 .filter_map(|origin| origin.extension_id())
879 .collect()
880 }
881
882 serialize_method!();
883}
884
885impl ScalarType {
886 pub fn iter_origins(&self) -> impl Iterator<Item = &ComponentOrigin> {
891 self.directives.iter().map(|dir| &dir.origin)
892 }
893
894 pub fn extensions(&self) -> IndexSet<&ExtensionId> {
899 self.iter_origins()
900 .filter_map(|origin| origin.extension_id())
901 .collect()
902 }
903
904 serialize_method!();
905}
906
907impl ObjectType {
908 pub fn iter_origins(&self) -> impl Iterator<Item = &ComponentOrigin> {
913 self.directives
914 .iter()
915 .map(|dir| &dir.origin)
916 .chain(
917 self.implements_interfaces
918 .iter()
919 .map(|component| &component.origin),
920 )
921 .chain(self.fields.values().map(|field| &field.origin))
922 }
923
924 pub fn extensions(&self) -> IndexSet<&ExtensionId> {
929 self.iter_origins()
930 .filter_map(|origin| origin.extension_id())
931 .collect()
932 }
933
934 serialize_method!();
935}
936
937impl InterfaceType {
938 pub fn iter_origins(&self) -> impl Iterator<Item = &ComponentOrigin> {
943 self.directives
944 .iter()
945 .map(|dir| &dir.origin)
946 .chain(
947 self.implements_interfaces
948 .iter()
949 .map(|component| &component.origin),
950 )
951 .chain(self.fields.values().map(|field| &field.origin))
952 }
953
954 pub fn extensions(&self) -> IndexSet<&ExtensionId> {
959 self.iter_origins()
960 .filter_map(|origin| origin.extension_id())
961 .collect()
962 }
963
964 serialize_method!();
965}
966
967impl UnionType {
968 pub fn iter_origins(&self) -> impl Iterator<Item = &ComponentOrigin> {
973 self.directives
974 .iter()
975 .map(|dir| &dir.origin)
976 .chain(self.members.iter().map(|component| &component.origin))
977 }
978
979 pub fn extensions(&self) -> IndexSet<&ExtensionId> {
984 self.iter_origins()
985 .filter_map(|origin| origin.extension_id())
986 .collect()
987 }
988
989 serialize_method!();
990}
991
992impl EnumType {
993 pub fn iter_origins(&self) -> impl Iterator<Item = &ComponentOrigin> {
998 self.directives
999 .iter()
1000 .map(|dir| &dir.origin)
1001 .chain(self.values.values().map(|value| &value.origin))
1002 }
1003
1004 pub fn extensions(&self) -> IndexSet<&ExtensionId> {
1009 self.iter_origins()
1010 .filter_map(|origin| origin.extension_id())
1011 .collect()
1012 }
1013
1014 serialize_method!();
1015}
1016
1017impl InputObjectType {
1018 pub fn iter_origins(&self) -> impl Iterator<Item = &ComponentOrigin> {
1023 self.directives
1024 .iter()
1025 .map(|dir| &dir.origin)
1026 .chain(self.fields.values().map(|field| &field.origin))
1027 }
1028
1029 pub fn extensions(&self) -> IndexSet<&ExtensionId> {
1034 self.iter_origins()
1035 .filter_map(|origin| origin.extension_id())
1036 .collect()
1037 }
1038
1039 serialize_method!();
1040}
1041
1042impl DirectiveList {
1043 pub const fn new() -> Self {
1044 Self(Vec::new())
1045 }
1046
1047 pub fn get_all<'def: 'name, 'name>(
1052 &'def self,
1053 name: &'name str,
1054 ) -> impl Iterator<Item = &'def Component<Directive>> + 'name {
1055 self.0.iter().filter(move |dir| dir.name == name)
1056 }
1057
1058 pub fn get(&self, name: &str) -> Option<&Component<Directive>> {
1063 self.get_all(name).next()
1064 }
1065
1066 pub fn has(&self, name: &str) -> bool {
1068 self.get(name).is_some()
1069 }
1070
1071 pub(crate) fn iter_ast(&self) -> impl Iterator<Item = &Node<ast::Directive>> {
1072 self.0.iter().map(|component| &component.node)
1073 }
1074
1075 pub fn push(&mut self, directive: impl Into<Component<Directive>>) {
1077 self.0.push(directive.into());
1078 }
1079
1080 serialize_method!();
1081}
1082
1083impl std::fmt::Debug for DirectiveList {
1084 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1085 self.0.fmt(f)
1086 }
1087}
1088
1089impl std::ops::Deref for DirectiveList {
1090 type Target = Vec<Component<Directive>>;
1091
1092 fn deref(&self) -> &Self::Target {
1093 &self.0
1094 }
1095}
1096
1097impl std::ops::DerefMut for DirectiveList {
1098 fn deref_mut(&mut self) -> &mut Self::Target {
1099 &mut self.0
1100 }
1101}
1102
1103impl IntoIterator for DirectiveList {
1104 type Item = Component<Directive>;
1105
1106 type IntoIter = std::vec::IntoIter<Component<Directive>>;
1107
1108 fn into_iter(self) -> Self::IntoIter {
1109 self.0.into_iter()
1110 }
1111}
1112
1113impl<'a> IntoIterator for &'a DirectiveList {
1114 type Item = &'a Component<Directive>;
1115
1116 type IntoIter = std::slice::Iter<'a, Component<Directive>>;
1117
1118 fn into_iter(self) -> Self::IntoIter {
1119 self.0.iter()
1120 }
1121}
1122
1123impl<'a> IntoIterator for &'a mut DirectiveList {
1124 type Item = &'a mut Component<Directive>;
1125
1126 type IntoIter = std::slice::IterMut<'a, Component<Directive>>;
1127
1128 fn into_iter(self) -> Self::IntoIter {
1129 self.0.iter_mut()
1130 }
1131}
1132
1133impl<D> FromIterator<D> for DirectiveList
1134where
1135 D: Into<Component<Directive>>,
1136{
1137 fn from_iter<T: IntoIterator<Item = D>>(iter: T) -> Self {
1138 Self(iter.into_iter().map(Into::into).collect())
1139 }
1140}
1141
1142impl Eq for Schema {}
1143
1144impl PartialEq for Schema {
1145 fn eq(&self, other: &Self) -> bool {
1146 let Self {
1147 sources: _, schema_definition,
1149 directive_definitions,
1150 types,
1151 } = self;
1152 *schema_definition == other.schema_definition
1153 && *directive_definitions == other.directive_definitions
1154 && *types == other.types
1155 }
1156}
1157
1158impl Implementers {
1159 pub fn iter(&self) -> impl Iterator<Item = &'_ Name> {
1163 self.objects.iter().chain(&self.interfaces)
1164 }
1165}
1166
1167impl From<Node<ScalarType>> for ExtendedType {
1168 fn from(ty: Node<ScalarType>) -> Self {
1169 Self::Scalar(ty)
1170 }
1171}
1172
1173impl From<Node<ObjectType>> for ExtendedType {
1174 fn from(ty: Node<ObjectType>) -> Self {
1175 Self::Object(ty)
1176 }
1177}
1178
1179impl From<Node<InterfaceType>> for ExtendedType {
1180 fn from(ty: Node<InterfaceType>) -> Self {
1181 Self::Interface(ty)
1182 }
1183}
1184
1185impl From<Node<UnionType>> for ExtendedType {
1186 fn from(ty: Node<UnionType>) -> Self {
1187 Self::Union(ty)
1188 }
1189}
1190
1191impl From<Node<EnumType>> for ExtendedType {
1192 fn from(ty: Node<EnumType>) -> Self {
1193 Self::Enum(ty)
1194 }
1195}
1196
1197impl From<Node<InputObjectType>> for ExtendedType {
1198 fn from(ty: Node<InputObjectType>) -> Self {
1199 Self::InputObject(ty)
1200 }
1201}
1202
1203impl From<ScalarType> for ExtendedType {
1204 fn from(ty: ScalarType) -> Self {
1205 Self::Scalar(ty.into())
1206 }
1207}
1208
1209impl From<ObjectType> for ExtendedType {
1210 fn from(ty: ObjectType) -> Self {
1211 Self::Object(ty.into())
1212 }
1213}
1214
1215impl From<InterfaceType> for ExtendedType {
1216 fn from(ty: InterfaceType) -> Self {
1217 Self::Interface(ty.into())
1218 }
1219}
1220
1221impl From<UnionType> for ExtendedType {
1222 fn from(ty: UnionType) -> Self {
1223 Self::Union(ty.into())
1224 }
1225}
1226
1227impl From<EnumType> for ExtendedType {
1228 fn from(ty: EnumType) -> Self {
1229 Self::Enum(ty.into())
1230 }
1231}
1232
1233impl From<InputObjectType> for ExtendedType {
1234 fn from(ty: InputObjectType) -> Self {
1235 Self::InputObject(ty.into())
1236 }
1237}
1238
1239impl std::fmt::Debug for Schema {
1240 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1241 let Self {
1242 sources,
1243 schema_definition,
1244 directive_definitions,
1245 types,
1246 } = self;
1247 f.debug_struct("Schema")
1248 .field("sources", sources)
1249 .field("schema_definition", schema_definition)
1250 .field(
1251 "directive_definitions",
1252 &DebugDirectiveDefinitions(directive_definitions),
1253 )
1254 .field("types", &DebugTypes(types))
1255 .finish()
1256 }
1257}
1258
1259struct DebugDirectiveDefinitions<'a>(&'a IndexMap<Name, Node<DirectiveDefinition>>);
1260
1261struct DebugTypes<'a>(&'a IndexMap<Name, ExtendedType>);
1262
1263impl std::fmt::Debug for DebugDirectiveDefinitions<'_> {
1264 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1265 let mut map = f.debug_map();
1266 for (name, def) in self.0 {
1267 if !def.is_built_in() {
1268 map.entry(name, def);
1269 } else {
1270 map.entry(name, &format_args!("built_in_directive!({name:?})"));
1271 }
1272 }
1273 map.finish()
1274 }
1275}
1276
1277impl std::fmt::Debug for DebugTypes<'_> {
1278 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1279 let mut map = f.debug_map();
1280 for (name, def) in self.0 {
1281 if !def.is_built_in() {
1282 map.entry(name, def);
1283 } else {
1284 map.entry(name, &format_args!("built_in_type!({name:?})"));
1285 }
1286 }
1287 map.finish()
1288 }
1289}
1290
1291struct MetaFieldDefinitions {
1292 __typename: Component<FieldDefinition>,
1293 __schema: Component<FieldDefinition>,
1294 __type: Component<FieldDefinition>,
1295}
1296
1297impl MetaFieldDefinitions {
1298 fn get() -> &'static Self {
1299 static DEFS: OnceLock<MetaFieldDefinitions> = OnceLock::new();
1300 DEFS.get_or_init(|| Self {
1301 __typename: Component::new(FieldDefinition {
1303 description: None,
1304 name: name!("__typename"),
1305 arguments: Vec::new(),
1306 ty: ty!(String!),
1307 directives: ast::DirectiveList::new(),
1308 }),
1309 __schema: Component::new(FieldDefinition {
1311 description: None,
1312 name: name!("__schema"),
1313 arguments: Vec::new(),
1314 ty: ty!(__Schema!),
1315 directives: ast::DirectiveList::new(),
1316 }),
1317 __type: Component::new(FieldDefinition {
1319 description: None,
1320 name: name!("__type"),
1321 arguments: vec![InputValueDefinition {
1322 description: None,
1323 name: name!("name"),
1324 ty: ty!(String!).into(),
1325 default_value: None,
1326 directives: ast::DirectiveList::new(),
1327 }
1328 .into()],
1329 ty: ty!(__Type),
1330 directives: ast::DirectiveList::new(),
1331 }),
1332 })
1333 }
1334}