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("directive extension for undefined directive `@{name}`")]
311 OrphanDirectiveExtension { name: Name },
312
313 #[error("adding {describe_ext}, but `{name}` is {describe_def}")]
314 TypeExtensionKindMismatch {
315 name: Name,
316 describe_ext: &'static str,
317 def_location: Option<SourceSpan>,
318 describe_def: &'static str,
319 },
320
321 #[error("duplicate definitions for the `{operation_type}` root operation type")]
322 DuplicateRootOperation {
323 previous_location: Option<SourceSpan>,
324 operation_type: &'static str,
325 },
326
327 #[error(
328 "object type `{type_name}` implements interface `{name_at_previous_location}` \
329 more than once"
330 )]
331 DuplicateImplementsInterfaceInObject {
332 name_at_previous_location: Name,
333 type_name: Name,
334 },
335
336 #[error(
337 "interface type `{type_name}` implements interface `{name_at_previous_location}` \
338 more than once"
339 )]
340 DuplicateImplementsInterfaceInInterface {
341 name_at_previous_location: Name,
342 type_name: Name,
343 },
344
345 #[error(
346 "duplicate definitions for the `{name_at_previous_location}` \
347 field of object type `{type_name}`"
348 )]
349 ObjectFieldNameCollision {
350 name_at_previous_location: Name,
351 type_name: Name,
352 },
353
354 #[error(
355 "duplicate definitions for the `{name_at_previous_location}` \
356 field of interface type `{type_name}`"
357 )]
358 InterfaceFieldNameCollision {
359 name_at_previous_location: Name,
360 type_name: Name,
361 },
362
363 #[error(
364 "duplicate definitions for the `{name_at_previous_location}` \
365 value of enum type `{type_name}`"
366 )]
367 EnumValueNameCollision {
368 name_at_previous_location: Name,
369 type_name: Name,
370 },
371
372 #[error(
373 "duplicate definitions for the `{name_at_previous_location}` \
374 member of union type `{type_name}`"
375 )]
376 UnionMemberNameCollision {
377 name_at_previous_location: Name,
378 type_name: Name,
379 },
380
381 #[error(
382 "duplicate definitions for the `{name_at_previous_location}` \
383 field of input object type `{type_name}`"
384 )]
385 InputFieldNameCollision {
386 name_at_previous_location: Name,
387 type_name: Name,
388 },
389}
390
391#[derive(Debug, Clone, PartialEq, Eq)]
393pub enum FieldLookupError<'schema> {
394 NoSuchType,
395 NoSuchField(&'schema NamedType, &'schema ExtendedType),
396}
397
398impl Schema {
399 #[allow(clippy::new_without_default)] pub fn new() -> Self {
405 SchemaBuilder::new().build().unwrap()
406 }
407
408 #[allow(clippy::result_large_err)] pub fn parse(
414 source_text: impl Into<String>,
415 path: impl AsRef<Path>,
416 ) -> Result<Self, WithErrors<Self>> {
417 Parser::default().parse_schema(source_text, path)
418 }
419
420 #[allow(clippy::result_large_err)] pub fn parse_and_validate(
424 source_text: impl Into<String>,
425 path: impl AsRef<Path>,
426 ) -> Result<Valid<Self>, WithErrors<Self>> {
427 let mut builder = Schema::builder();
428 Parser::default().parse_into_schema_builder(source_text, path, &mut builder);
429 let (mut schema, mut errors) = builder.build_inner();
430 validation::validate_schema(&mut errors, &mut schema);
431 errors.into_valid_result(schema)
432 }
433
434 pub fn builder() -> SchemaBuilder {
443 SchemaBuilder::new()
444 }
445
446 #[allow(clippy::result_large_err)] pub fn validate(mut self) -> Result<Valid<Self>, WithErrors<Self>> {
448 let mut errors = DiagnosticList::new(self.sources.clone());
449 validation::validate_schema(&mut errors, &mut self);
450 errors.into_valid_result(self)
451 }
452
453 pub fn get_scalar(&self, name: &str) -> Option<&Node<ScalarType>> {
455 if let Some(ExtendedType::Scalar(ty)) = self.types.get(name) {
456 Some(ty)
457 } else {
458 None
459 }
460 }
461
462 pub fn get_object(&self, name: &str) -> Option<&Node<ObjectType>> {
464 if let Some(ExtendedType::Object(ty)) = self.types.get(name) {
465 Some(ty)
466 } else {
467 None
468 }
469 }
470
471 pub fn get_interface(&self, name: &str) -> Option<&Node<InterfaceType>> {
473 if let Some(ExtendedType::Interface(ty)) = self.types.get(name) {
474 Some(ty)
475 } else {
476 None
477 }
478 }
479
480 pub fn get_union(&self, name: &str) -> Option<&Node<UnionType>> {
482 if let Some(ExtendedType::Union(ty)) = self.types.get(name) {
483 Some(ty)
484 } else {
485 None
486 }
487 }
488
489 pub fn get_enum(&self, name: &str) -> Option<&Node<EnumType>> {
491 if let Some(ExtendedType::Enum(ty)) = self.types.get(name) {
492 Some(ty)
493 } else {
494 None
495 }
496 }
497
498 pub fn get_input_object(&self, name: &str) -> Option<&Node<InputObjectType>> {
500 if let Some(ExtendedType::InputObject(ty)) = self.types.get(name) {
501 Some(ty)
502 } else {
503 None
504 }
505 }
506
507 pub fn root_operation(&self, operation_type: ast::OperationType) -> Option<&NamedType> {
509 match operation_type {
510 ast::OperationType::Query => &self.schema_definition.query,
511 ast::OperationType::Mutation => &self.schema_definition.mutation,
512 ast::OperationType::Subscription => &self.schema_definition.subscription,
513 }
514 .as_ref()
515 .map(|component| &component.name)
516 }
517
518 pub fn type_field(
520 &self,
521 type_name: &str,
522 field_name: &str,
523 ) -> Result<&Component<FieldDefinition>, FieldLookupError<'_>> {
524 use ExtendedType::*;
525 let (ty_def_name, ty_def) = self
526 .types
527 .get_key_value(type_name)
528 .ok_or(FieldLookupError::NoSuchType)?;
529 let explicit_field = match ty_def {
530 Object(ty) => ty.fields.get(field_name),
531 Interface(ty) => ty.fields.get(field_name),
532 Scalar(_) | Union(_) | Enum(_) | InputObject(_) => None,
533 };
534 if let Some(def) = explicit_field {
535 return Ok(def);
536 }
537 let meta = MetaFieldDefinitions::get();
538 if field_name == "__typename" && matches!(ty_def, Object(_) | Interface(_) | Union(_)) {
539 return Ok(&meta.__typename);
541 }
542 if self
543 .schema_definition
544 .query
545 .as_ref()
546 .is_some_and(|query_type| query_type == type_name)
547 {
548 match field_name {
549 "__schema" => return Ok(&meta.__schema),
550 "__type" => return Ok(&meta.__type),
551 _ => {}
552 }
553 }
554 Err(FieldLookupError::NoSuchField(ty_def_name, ty_def))
555 }
556
557 pub fn implementers_map(&self) -> HashMap<Name, Implementers> {
566 let mut map = HashMap::<Name, Implementers>::default();
567 for (ty_name, ty) in &self.types {
568 match ty {
569 ExtendedType::Object(def) => {
570 for interface in &def.implements_interfaces {
571 map.entry(interface.name.clone())
572 .or_default()
573 .objects
574 .insert(ty_name.clone());
575 }
576 }
577 ExtendedType::Interface(def) => {
578 for interface in &def.implements_interfaces {
579 map.entry(interface.name.clone())
580 .or_default()
581 .interfaces
582 .insert(ty_name.clone());
583 }
584 }
585 ExtendedType::Scalar(_)
586 | ExtendedType::Union(_)
587 | ExtendedType::Enum(_)
588 | ExtendedType::InputObject(_) => (),
589 };
590 }
591 map
592 }
593
594 pub fn is_subtype(&self, abstract_type: &str, maybe_subtype: &str) -> bool {
599 self.types.get(abstract_type).is_some_and(|ty| match ty {
600 ExtendedType::Interface(_) => self.types.get(maybe_subtype).is_some_and(|ty2| {
601 match ty2 {
602 ExtendedType::Object(def) => &def.implements_interfaces,
603 ExtendedType::Interface(def) => &def.implements_interfaces,
604 ExtendedType::Scalar(_)
605 | ExtendedType::Union(_)
606 | ExtendedType::Enum(_)
607 | ExtendedType::InputObject(_) => return false,
608 }
609 .contains(abstract_type)
610 }),
611 ExtendedType::Union(def) => def.members.contains(maybe_subtype),
612 ExtendedType::Scalar(_)
613 | ExtendedType::Object(_)
614 | ExtendedType::Enum(_)
615 | ExtendedType::InputObject(_) => false,
616 })
617 }
618
619 pub fn is_input_type(&self, ty: &Type) -> bool {
623 match self.types.get(ty.inner_named_type()) {
624 Some(ExtendedType::Scalar(_))
625 | Some(ExtendedType::Enum(_))
626 | Some(ExtendedType::InputObject(_)) => true,
627 Some(ExtendedType::Object(_))
628 | Some(ExtendedType::Interface(_))
629 | Some(ExtendedType::Union(_))
630 | None => false,
631 }
632 }
633
634 pub fn is_output_type(&self, ty: &Type) -> bool {
638 match self.types.get(ty.inner_named_type()) {
639 Some(ExtendedType::Scalar(_))
640 | Some(ExtendedType::Object(_))
641 | Some(ExtendedType::Interface(_))
642 | Some(ExtendedType::Union(_))
643 | Some(ExtendedType::Enum(_)) => true,
644 Some(ExtendedType::InputObject(_)) | None => false,
645 }
646 }
647
648 serialize_method!();
649}
650
651impl SchemaDefinition {
652 pub fn iter_root_operations(
653 &self,
654 ) -> impl Iterator<Item = (ast::OperationType, &ComponentName)> {
655 [
656 (ast::OperationType::Query, &self.query),
657 (ast::OperationType::Mutation, &self.mutation),
658 (ast::OperationType::Subscription, &self.subscription),
659 ]
660 .into_iter()
661 .filter_map(|(ty, maybe_op)| maybe_op.as_ref().map(|op| (ty, op)))
662 }
663
664 pub fn iter_origins(&self) -> impl Iterator<Item = &ComponentOrigin> {
669 self.directives
670 .iter()
671 .map(|dir| &dir.origin)
672 .chain(self.query.iter().map(|name| &name.origin))
673 .chain(self.mutation.iter().map(|name| &name.origin))
674 .chain(self.subscription.iter().map(|name| &name.origin))
675 }
676
677 pub fn extensions(&self) -> IndexSet<&ExtensionId> {
682 self.iter_origins()
683 .filter_map(|origin| origin.extension_id())
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 pub fn iter_origins(&self) -> impl Iterator<Item = &ComponentOrigin> {
865 match self {
866 Self::Scalar(ty) => Box::new(ty.iter_origins()) as Box<dyn Iterator<Item = _>>,
867 Self::Object(ty) => Box::new(ty.iter_origins()),
868 Self::Interface(ty) => Box::new(ty.iter_origins()),
869 Self::Union(ty) => Box::new(ty.iter_origins()),
870 Self::Enum(ty) => Box::new(ty.iter_origins()),
871 Self::InputObject(ty) => Box::new(ty.iter_origins()),
872 }
873 }
874
875 pub fn extensions(&self) -> IndexSet<&ExtensionId> {
880 self.iter_origins()
881 .filter_map(|origin| origin.extension_id())
882 .collect()
883 }
884
885 serialize_method!();
886}
887
888impl ScalarType {
889 pub fn iter_origins(&self) -> impl Iterator<Item = &ComponentOrigin> {
894 self.directives.iter().map(|dir| &dir.origin)
895 }
896
897 pub fn extensions(&self) -> IndexSet<&ExtensionId> {
902 self.iter_origins()
903 .filter_map(|origin| origin.extension_id())
904 .collect()
905 }
906
907 serialize_method!();
908}
909
910impl ObjectType {
911 pub fn iter_origins(&self) -> impl Iterator<Item = &ComponentOrigin> {
916 self.directives
917 .iter()
918 .map(|dir| &dir.origin)
919 .chain(
920 self.implements_interfaces
921 .iter()
922 .map(|component| &component.origin),
923 )
924 .chain(self.fields.values().map(|field| &field.origin))
925 }
926
927 pub fn extensions(&self) -> IndexSet<&ExtensionId> {
932 self.iter_origins()
933 .filter_map(|origin| origin.extension_id())
934 .collect()
935 }
936
937 serialize_method!();
938}
939
940impl InterfaceType {
941 pub fn iter_origins(&self) -> impl Iterator<Item = &ComponentOrigin> {
946 self.directives
947 .iter()
948 .map(|dir| &dir.origin)
949 .chain(
950 self.implements_interfaces
951 .iter()
952 .map(|component| &component.origin),
953 )
954 .chain(self.fields.values().map(|field| &field.origin))
955 }
956
957 pub fn extensions(&self) -> IndexSet<&ExtensionId> {
962 self.iter_origins()
963 .filter_map(|origin| origin.extension_id())
964 .collect()
965 }
966
967 serialize_method!();
968}
969
970impl UnionType {
971 pub fn iter_origins(&self) -> impl Iterator<Item = &ComponentOrigin> {
976 self.directives
977 .iter()
978 .map(|dir| &dir.origin)
979 .chain(self.members.iter().map(|component| &component.origin))
980 }
981
982 pub fn extensions(&self) -> IndexSet<&ExtensionId> {
987 self.iter_origins()
988 .filter_map(|origin| origin.extension_id())
989 .collect()
990 }
991
992 serialize_method!();
993}
994
995impl EnumType {
996 pub fn iter_origins(&self) -> impl Iterator<Item = &ComponentOrigin> {
1001 self.directives
1002 .iter()
1003 .map(|dir| &dir.origin)
1004 .chain(self.values.values().map(|value| &value.origin))
1005 }
1006
1007 pub fn extensions(&self) -> IndexSet<&ExtensionId> {
1012 self.iter_origins()
1013 .filter_map(|origin| origin.extension_id())
1014 .collect()
1015 }
1016
1017 serialize_method!();
1018}
1019
1020impl InputObjectType {
1021 pub fn iter_origins(&self) -> impl Iterator<Item = &ComponentOrigin> {
1026 self.directives
1027 .iter()
1028 .map(|dir| &dir.origin)
1029 .chain(self.fields.values().map(|field| &field.origin))
1030 }
1031
1032 pub fn extensions(&self) -> IndexSet<&ExtensionId> {
1037 self.iter_origins()
1038 .filter_map(|origin| origin.extension_id())
1039 .collect()
1040 }
1041
1042 serialize_method!();
1043}
1044
1045impl DirectiveList {
1046 pub const fn new() -> Self {
1047 Self(Vec::new())
1048 }
1049
1050 pub fn get_all<'def: 'name, 'name>(
1055 &'def self,
1056 name: &'name str,
1057 ) -> impl Iterator<Item = &'def Component<Directive>> + 'name {
1058 self.0.iter().filter(move |dir| dir.name == name)
1059 }
1060
1061 pub fn get(&self, name: &str) -> Option<&Component<Directive>> {
1066 self.get_all(name).next()
1067 }
1068
1069 pub fn has(&self, name: &str) -> bool {
1071 self.get(name).is_some()
1072 }
1073
1074 pub(crate) fn iter_ast(&self) -> impl Iterator<Item = &Node<ast::Directive>> {
1075 self.0.iter().map(|component| &component.node)
1076 }
1077
1078 pub fn push(&mut self, directive: impl Into<Component<Directive>>) {
1080 self.0.push(directive.into());
1081 }
1082
1083 serialize_method!();
1084}
1085
1086impl std::fmt::Debug for DirectiveList {
1087 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1088 self.0.fmt(f)
1089 }
1090}
1091
1092impl std::ops::Deref for DirectiveList {
1093 type Target = Vec<Component<Directive>>;
1094
1095 fn deref(&self) -> &Self::Target {
1096 &self.0
1097 }
1098}
1099
1100impl std::ops::DerefMut for DirectiveList {
1101 fn deref_mut(&mut self) -> &mut Self::Target {
1102 &mut self.0
1103 }
1104}
1105
1106impl IntoIterator for DirectiveList {
1107 type Item = Component<Directive>;
1108
1109 type IntoIter = std::vec::IntoIter<Component<Directive>>;
1110
1111 fn into_iter(self) -> Self::IntoIter {
1112 self.0.into_iter()
1113 }
1114}
1115
1116impl<'a> IntoIterator for &'a DirectiveList {
1117 type Item = &'a Component<Directive>;
1118
1119 type IntoIter = std::slice::Iter<'a, Component<Directive>>;
1120
1121 fn into_iter(self) -> Self::IntoIter {
1122 self.0.iter()
1123 }
1124}
1125
1126impl<'a> IntoIterator for &'a mut DirectiveList {
1127 type Item = &'a mut Component<Directive>;
1128
1129 type IntoIter = std::slice::IterMut<'a, Component<Directive>>;
1130
1131 fn into_iter(self) -> Self::IntoIter {
1132 self.0.iter_mut()
1133 }
1134}
1135
1136impl<D> FromIterator<D> for DirectiveList
1137where
1138 D: Into<Component<Directive>>,
1139{
1140 fn from_iter<T: IntoIterator<Item = D>>(iter: T) -> Self {
1141 Self(iter.into_iter().map(Into::into).collect())
1142 }
1143}
1144
1145impl Eq for Schema {}
1146
1147impl PartialEq for Schema {
1148 fn eq(&self, other: &Self) -> bool {
1149 let Self {
1150 sources: _, schema_definition,
1152 directive_definitions,
1153 types,
1154 } = self;
1155 *schema_definition == other.schema_definition
1156 && *directive_definitions == other.directive_definitions
1157 && *types == other.types
1158 }
1159}
1160
1161impl Implementers {
1162 pub fn iter(&self) -> impl Iterator<Item = &'_ Name> {
1166 self.objects.iter().chain(&self.interfaces)
1167 }
1168}
1169
1170impl From<Node<ScalarType>> for ExtendedType {
1171 fn from(ty: Node<ScalarType>) -> Self {
1172 Self::Scalar(ty)
1173 }
1174}
1175
1176impl From<Node<ObjectType>> for ExtendedType {
1177 fn from(ty: Node<ObjectType>) -> Self {
1178 Self::Object(ty)
1179 }
1180}
1181
1182impl From<Node<InterfaceType>> for ExtendedType {
1183 fn from(ty: Node<InterfaceType>) -> Self {
1184 Self::Interface(ty)
1185 }
1186}
1187
1188impl From<Node<UnionType>> for ExtendedType {
1189 fn from(ty: Node<UnionType>) -> Self {
1190 Self::Union(ty)
1191 }
1192}
1193
1194impl From<Node<EnumType>> for ExtendedType {
1195 fn from(ty: Node<EnumType>) -> Self {
1196 Self::Enum(ty)
1197 }
1198}
1199
1200impl From<Node<InputObjectType>> for ExtendedType {
1201 fn from(ty: Node<InputObjectType>) -> Self {
1202 Self::InputObject(ty)
1203 }
1204}
1205
1206impl From<ScalarType> for ExtendedType {
1207 fn from(ty: ScalarType) -> Self {
1208 Self::Scalar(ty.into())
1209 }
1210}
1211
1212impl From<ObjectType> for ExtendedType {
1213 fn from(ty: ObjectType) -> Self {
1214 Self::Object(ty.into())
1215 }
1216}
1217
1218impl From<InterfaceType> for ExtendedType {
1219 fn from(ty: InterfaceType) -> Self {
1220 Self::Interface(ty.into())
1221 }
1222}
1223
1224impl From<UnionType> for ExtendedType {
1225 fn from(ty: UnionType) -> Self {
1226 Self::Union(ty.into())
1227 }
1228}
1229
1230impl From<EnumType> for ExtendedType {
1231 fn from(ty: EnumType) -> Self {
1232 Self::Enum(ty.into())
1233 }
1234}
1235
1236impl From<InputObjectType> for ExtendedType {
1237 fn from(ty: InputObjectType) -> Self {
1238 Self::InputObject(ty.into())
1239 }
1240}
1241
1242impl std::fmt::Debug for Schema {
1243 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1244 let Self {
1245 sources,
1246 schema_definition,
1247 directive_definitions,
1248 types,
1249 } = self;
1250 f.debug_struct("Schema")
1251 .field("sources", sources)
1252 .field("schema_definition", schema_definition)
1253 .field(
1254 "directive_definitions",
1255 &DebugDirectiveDefinitions(directive_definitions),
1256 )
1257 .field("types", &DebugTypes(types))
1258 .finish()
1259 }
1260}
1261
1262struct DebugDirectiveDefinitions<'a>(&'a IndexMap<Name, Node<DirectiveDefinition>>);
1263
1264struct DebugTypes<'a>(&'a IndexMap<Name, ExtendedType>);
1265
1266impl std::fmt::Debug for DebugDirectiveDefinitions<'_> {
1267 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1268 let mut map = f.debug_map();
1269 for (name, def) in self.0 {
1270 if !def.is_built_in() {
1271 map.entry(name, def);
1272 } else {
1273 map.entry(name, &format_args!("built_in_directive!({name:?})"));
1274 }
1275 }
1276 map.finish()
1277 }
1278}
1279
1280impl std::fmt::Debug for DebugTypes<'_> {
1281 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1282 let mut map = f.debug_map();
1283 for (name, def) in self.0 {
1284 if !def.is_built_in() {
1285 map.entry(name, def);
1286 } else {
1287 map.entry(name, &format_args!("built_in_type!({name:?})"));
1288 }
1289 }
1290 map.finish()
1291 }
1292}
1293
1294struct MetaFieldDefinitions {
1295 __typename: Component<FieldDefinition>,
1296 __schema: Component<FieldDefinition>,
1297 __type: Component<FieldDefinition>,
1298}
1299
1300impl MetaFieldDefinitions {
1301 fn get() -> &'static Self {
1302 static DEFS: OnceLock<MetaFieldDefinitions> = OnceLock::new();
1303 DEFS.get_or_init(|| Self {
1304 __typename: Component::new(FieldDefinition {
1306 description: None,
1307 name: name!("__typename"),
1308 arguments: Vec::new(),
1309 ty: ty!(String!),
1310 directives: ast::DirectiveList::new(),
1311 }),
1312 __schema: Component::new(FieldDefinition {
1314 description: None,
1315 name: name!("__schema"),
1316 arguments: Vec::new(),
1317 ty: ty!(__Schema!),
1318 directives: ast::DirectiveList::new(),
1319 }),
1320 __type: Component::new(FieldDefinition {
1322 description: None,
1323 name: name!("__type"),
1324 arguments: vec![InputValueDefinition {
1325 description: None,
1326 name: name!("name"),
1327 ty: ty!(String!).into(),
1328 default_value: None,
1329 directives: ast::DirectiveList::new(),
1330 }
1331 .into()],
1332 ty: ty!(__Type),
1333 directives: ast::DirectiveList::new(),
1334 }),
1335 })
1336 }
1337}