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>
104 = std::iter::Map<
105 Values<'b, &'b str, &'b TypeDefinition<'a, C>>,
106 fn(&&'b TypeDefinition<'a, C>) -> TypeDefinitionReference<'b, TypeDefinition<'a, C>>,
107 >
108 where
109 'a: 'b;
110 type DirectiveDefinitions<'b>
111 = std::iter::Copied<Values<'b, &'b str, &'b DirectiveDefinition<'a, C>>>
112 where
113 'a: 'b;
114 type InterfaceImplementors<'b>
115 = std::iter::Flatten<
116 std::option::IntoIter<
117 std::iter::Copied<std::slice::Iter<'b, &'b ObjectTypeDefinition<'a, C>>>,
118 >,
119 >
120 where
121 'a: 'b;
122
123 fn description(&self) -> Option<&str> {
124 self.description.as_ref().map(AsRef::as_ref)
125 }
126
127 fn query(&self) -> &Self::ObjectTypeDefinition {
128 self.query
129 }
130
131 fn mutation(&self) -> Option<&Self::ObjectTypeDefinition> {
132 self.mutation
133 }
134
135 fn subscription(&self) -> Option<&Self::ObjectTypeDefinition> {
136 self.subscription
137 }
138
139 fn get_type_definition(
140 &self,
141 name: &str,
142 ) -> Option<TypeDefinitionReference<'_, Self::TypeDefinition>> {
143 self.type_definitions.get(name).map(|td| td.as_ref())
144 }
145
146 fn type_definitions(&self) -> Self::TypeDefinitions<'_> {
147 self.type_definitions.values().map(
148 |td: &&TypeDefinition<C>| -> TypeDefinitionReference<'_, TypeDefinition<'a, C>> {
149 td.as_ref()
150 },
151 )
152 }
153
154 fn get_directive_definition(&self, name: &str) -> Option<&Self::DirectiveDefinition> {
155 self.directive_definitions.get(name).copied()
156 }
157
158 fn directive_definitions(&self) -> Self::DirectiveDefinitions<'_> {
159 self.directive_definitions.values().copied()
160 }
161
162 fn get_interface_implementors(
163 &self,
164 itd: &Self::InterfaceTypeDefinition,
165 ) -> Self::InterfaceImplementors<'_> {
166 self.interface_implementors
167 .get(itd.name().as_ref())
168 .map(|implementors| implementors.iter().copied())
169 .into_iter()
170 .flatten()
171 }
172}
173
174impl<'a, C: Context> HasDirectives for SchemaDefinition<'a, C> {
175 type Directives = Directives<'a, C>;
176
177 fn directives(&self) -> Option<&Self::Directives> {
178 self.directives
179 }
180}