bluejay_parser/ast/definition/
schema_definition.rs1use crate::ast::definition::{
2 ArgumentsDefinition, Context, CustomScalarTypeDefinition, DefaultContext, Directive,
3 DirectiveDefinition, Directives, EnumTypeDefinition, EnumValueDefinition, EnumValueDefinitions,
4 FieldDefinition, FieldsDefinition, InputFieldsDefinition, InputObjectTypeDefinition, InputType,
5 InputValueDefinition, InterfaceImplementation, InterfaceImplementations,
6 InterfaceTypeDefinition, ObjectTypeDefinition, OutputType, TypeDefinition, UnionMemberType,
7 UnionMemberTypes, UnionTypeDefinition,
8};
9use crate::lexical_token::StringValue;
10use bluejay_core::definition::{
11 HasDirectives, InterfaceImplementation as CoreInterfaceImplementation,
12 ObjectTypeDefinition as CoreObjectTypeDefinition, SchemaDefinition as CoreSchemaDefinition,
13 TypeDefinition as CoreTypeDefinition, TypeDefinitionReference,
14};
15use bluejay_core::AsIter;
16use std::collections::{btree_map::Values, BTreeMap, HashMap};
17
18#[derive(Debug)]
19pub struct SchemaDefinition<'a, C: Context = DefaultContext> {
20 type_definitions: BTreeMap<&'a str, &'a TypeDefinition<'a, C>>,
21 directive_definitions: BTreeMap<&'a str, &'a DirectiveDefinition<'a, C>>,
22 description: Option<&'a StringValue<'a>>,
23 query: &'a ObjectTypeDefinition<'a, C>,
24 mutation: Option<&'a ObjectTypeDefinition<'a, C>>,
25 subscription: Option<&'a ObjectTypeDefinition<'a, C>>,
26 directives: Option<&'a Directives<'a, C>>,
27 interface_implementors: HashMap<&'a str, Vec<&'a ObjectTypeDefinition<'a, C>>>,
28}
29
30impl<'a, C: Context> SchemaDefinition<'a, C> {
31 pub(crate) fn new(
32 type_definitions: BTreeMap<&'a str, &'a TypeDefinition<'a, C>>,
33 directive_definitions: BTreeMap<&'a str, &'a DirectiveDefinition<'a, C>>,
34 description: Option<&'a StringValue>,
35 query: &'a ObjectTypeDefinition<'a, C>,
36 mutation: Option<&'a ObjectTypeDefinition<'a, C>>,
37 subscription: Option<&'a ObjectTypeDefinition<'a, C>>,
38 directives: Option<&'a Directives<'a, C>>,
39 ) -> Self {
40 let interface_implementors = Self::interface_implementors(&type_definitions);
41 Self {
42 type_definitions,
43 directive_definitions,
44 description,
45 query,
46 mutation,
47 subscription,
48 directives,
49 interface_implementors,
50 }
51 }
52
53 fn interface_implementors(
54 type_definitions: &BTreeMap<&'a str, &'a TypeDefinition<'a, C>>,
55 ) -> HashMap<&'a str, Vec<&'a ObjectTypeDefinition<'a, C>>> {
56 type_definitions.values().fold(
57 HashMap::new(),
58 |mut interface_implementors, &type_definition| {
59 if let TypeDefinition::Object(otd) = type_definition {
60 if let Some(interface_implementations) = otd.interface_implementations() {
61 interface_implementations
62 .iter()
63 .for_each(|interface_implementation| {
64 let itd_name = interface_implementation.name();
65 interface_implementors
66 .entry(itd_name)
67 .or_default()
68 .push(otd);
69 });
70 }
71 }
72
73 interface_implementors
74 },
75 )
76 }
77}
78
79impl<'a, C: Context> CoreSchemaDefinition for SchemaDefinition<'a, C> {
80 type Directive = Directive<'a, C>;
81 type Directives = Directives<'a, C>;
82 type InputValueDefinition = InputValueDefinition<'a, C>;
83 type InputFieldsDefinition = InputFieldsDefinition<'a, C>;
84 type ArgumentsDefinition = ArgumentsDefinition<'a, C>;
85 type EnumValueDefinition = EnumValueDefinition<'a, C>;
86 type EnumValueDefinitions = EnumValueDefinitions<'a, C>;
87 type FieldDefinition = FieldDefinition<'a, C>;
88 type FieldsDefinition = FieldsDefinition<'a, C>;
89 type InterfaceImplementation = InterfaceImplementation<'a, C>;
90 type InterfaceImplementations = InterfaceImplementations<'a, C>;
91 type UnionMemberType = UnionMemberType<'a, C>;
92 type UnionMemberTypes = UnionMemberTypes<'a, C>;
93 type InputType = InputType<'a, C>;
94 type OutputType = OutputType<'a, C>;
95 type CustomScalarTypeDefinition = CustomScalarTypeDefinition<'a, C>;
96 type ObjectTypeDefinition = ObjectTypeDefinition<'a, C>;
97 type InterfaceTypeDefinition = InterfaceTypeDefinition<'a, C>;
98 type UnionTypeDefinition = UnionTypeDefinition<'a, C>;
99 type InputObjectTypeDefinition = InputObjectTypeDefinition<'a, C>;
100 type EnumTypeDefinition = EnumTypeDefinition<'a, C>;
101 type TypeDefinition = TypeDefinition<'a, C>;
102 type DirectiveDefinition = DirectiveDefinition<'a, C>;
103 type TypeDefinitions<'b> = std::iter::Map<
104 Values<'b, &'b str, &'b TypeDefinition<'a, C>>,
105 fn(&&'b TypeDefinition<'a, C>) -> TypeDefinitionReference<'b, TypeDefinition<'a, C>>
106 > where 'a: 'b;
107 type DirectiveDefinitions<'b> =
108 std::iter::Copied<Values<'b, &'b str, &'b DirectiveDefinition<'a, C>>> where 'a: 'b;
109 type InterfaceImplementors<'b> = std::iter::Flatten<std::option::IntoIter<std::iter::Copied<std::slice::Iter<'b, &'b ObjectTypeDefinition<'a, C>>>>> where 'a: 'b;
110
111 fn description(&self) -> Option<&str> {
112 self.description.as_ref().map(AsRef::as_ref)
113 }
114
115 fn query(&self) -> &Self::ObjectTypeDefinition {
116 self.query
117 }
118
119 fn mutation(&self) -> Option<&Self::ObjectTypeDefinition> {
120 self.mutation
121 }
122
123 fn subscription(&self) -> Option<&Self::ObjectTypeDefinition> {
124 self.subscription
125 }
126
127 fn get_type_definition(
128 &self,
129 name: &str,
130 ) -> Option<TypeDefinitionReference<'_, Self::TypeDefinition>> {
131 self.type_definitions.get(name).map(|td| td.as_ref())
132 }
133
134 fn type_definitions(&self) -> Self::TypeDefinitions<'_> {
135 self.type_definitions.values().map(
136 |td: &&TypeDefinition<C>| -> TypeDefinitionReference<'_, TypeDefinition<'a, C>> {
137 td.as_ref()
138 },
139 )
140 }
141
142 fn get_directive_definition(&self, name: &str) -> Option<&Self::DirectiveDefinition> {
143 self.directive_definitions.get(name).copied()
144 }
145
146 fn directive_definitions(&self) -> Self::DirectiveDefinitions<'_> {
147 self.directive_definitions.values().copied()
148 }
149
150 fn get_interface_implementors(
151 &self,
152 itd: &Self::InterfaceTypeDefinition,
153 ) -> Self::InterfaceImplementors<'_> {
154 self.interface_implementors
155 .get(itd.name().as_ref())
156 .map(|implementors| implementors.iter().copied())
157 .into_iter()
158 .flatten()
159 }
160}
161
162impl<'a, C: Context> HasDirectives for SchemaDefinition<'a, C> {
163 type Directives = Directives<'a, C>;
164
165 fn directives(&self) -> Option<&Self::Directives> {
166 self.directives
167 }
168}