1use std::collections::HashMap;
2
3use lazy_static::lazy_static;
4
5use crate::static_graphql::query::{
6 self, Directive, FragmentSpread, OperationDefinition, SelectionSet, Type, Value,
7 VariableDefinition,
8};
9use crate::static_graphql::schema::{
10 self, DirectiveDefinition, EnumValue, Field, InputValue, InterfaceType, ObjectType,
11 TypeDefinition, TypeExtension, UnionType,
12};
13
14lazy_static! {
15 static ref QUERY_TYPE_DEFAULT_NAME: String = "Query".to_string();
16 static ref MUTATION_TYPE_DEFAULT_NAME: String = "Mutation".to_string();
17 static ref SUBSCRIPTION_TYPE_DEFAULT_NAME: String = "Subscription".to_string();
18}
19
20impl TypeDefinition {
21 pub fn field_by_name(&self, name: &str) -> Option<&schema::Field> {
22 match self {
23 TypeDefinition::Object(object) => {
24 object.fields.iter().find(|field| field.name.eq(name))
25 }
26 TypeDefinition::Interface(interface) => {
27 interface.fields.iter().find(|field| field.name.eq(name))
28 }
29 _ => None,
30 }
31 }
32
33 pub fn input_field_by_name(&self, name: &str) -> Option<&InputValue> {
34 match self {
35 TypeDefinition::InputObject(input_object) => {
36 input_object.fields.iter().find(|field| field.name.eq(name))
37 }
38 _ => None,
39 }
40 }
41}
42
43impl OperationDefinition {
44 pub fn variable_definitions(&self) -> &[VariableDefinition] {
45 match self {
46 OperationDefinition::Query(query) => &query.variable_definitions,
47 OperationDefinition::SelectionSet(_) => &[],
48 OperationDefinition::Mutation(mutation) => &mutation.variable_definitions,
49 OperationDefinition::Subscription(subscription) => &subscription.variable_definitions,
50 }
51 }
52
53 pub fn selection_set(&self) -> &SelectionSet {
54 match self {
55 OperationDefinition::Query(query) => &query.selection_set,
56 OperationDefinition::SelectionSet(selection_set) => selection_set,
57 OperationDefinition::Mutation(mutation) => &mutation.selection_set,
58 OperationDefinition::Subscription(subscription) => &subscription.selection_set,
59 }
60 }
61
62 pub fn directives(&self) -> &[Directive] {
63 match self {
64 OperationDefinition::Query(query) => &query.directives,
65 OperationDefinition::SelectionSet(_) => &[],
66 OperationDefinition::Mutation(mutation) => &mutation.directives,
67 OperationDefinition::Subscription(subscription) => &subscription.directives,
68 }
69 }
70}
71
72impl schema::Document {
73 pub fn type_by_name(&self, name: &str) -> Option<&TypeDefinition> {
74 for def in &self.definitions {
75 if let schema::Definition::TypeDefinition(type_def) = def {
76 if type_def.name().eq(name) {
77 return Some(type_def);
78 }
79 }
80 }
81
82 None
83 }
84
85 pub fn directive_by_name(&self, name: &str) -> Option<&DirectiveDefinition> {
86 for def in &self.definitions {
87 if let schema::Definition::DirectiveDefinition(directive_def) = def {
88 if directive_def.name.eq(name) {
89 return Some(directive_def);
90 }
91 }
92 }
93
94 None
95 }
96
97 pub fn query_type(&self) -> &ObjectType {
98 self.query_type_name()
99 .and_then(|name| self.object_type_by_name(name))
100 .expect("invariant violation: every valid schema must define a query type")
101 }
102
103 pub fn mutation_type(&self) -> Option<&ObjectType> {
104 self.mutation_type_name()
105 .and_then(|name| self.object_type_by_name(name))
106 }
107
108 pub fn subscription_type(&self) -> Option<&ObjectType> {
109 self.subscription_type_name()
110 .and_then(|name| self.object_type_by_name(name))
111 }
112
113 fn object_type_by_name(&self, name: &str) -> Option<&ObjectType> {
114 match self.type_by_name(name) {
115 Some(TypeDefinition::Object(object_def)) => Some(object_def),
116 _ => None,
117 }
118 }
119
120 pub fn type_map(&self) -> HashMap<&str, &TypeDefinition> {
121 let mut type_map = HashMap::new();
122
123 for def in &self.definitions {
124 if let schema::Definition::TypeDefinition(type_def) = def {
125 type_map.insert(type_def.name(), type_def);
126 }
127 }
128
129 type_map
130 }
131
132 pub fn is_named_subtype(&self, sub_type_name: &str, super_type_name: &str) -> bool {
133 if sub_type_name == super_type_name {
134 true
135 } else if let (Some(sub_type), Some(super_type)) = (
136 self.type_by_name(sub_type_name),
137 self.type_by_name(super_type_name),
138 ) {
139 super_type.is_abstract_type() && self.is_possible_type(super_type, sub_type)
140 } else {
141 false
142 }
143 }
144
145 fn is_possible_type(
146 &self,
147 abstract_type: &TypeDefinition,
148 possible_type: &TypeDefinition,
149 ) -> bool {
150 match abstract_type {
151 TypeDefinition::Union(union_typedef) => union_typedef
152 .types
153 .iter()
154 .any(|t| t == possible_type.name()),
155 TypeDefinition::Interface(interface_typedef) => {
156 let implementes_interfaces = possible_type.interfaces();
157
158 implementes_interfaces.contains(&interface_typedef.name)
159 }
160 _ => false,
161 }
162 }
163
164 pub fn is_subtype(&self, sub_type: &Type, super_type: &Type) -> bool {
165 if sub_type == super_type {
167 return true;
168 }
169
170 if super_type.is_non_null() {
172 if sub_type.is_non_null() {
173 return self.is_subtype(sub_type.of_type(), super_type.of_type());
174 }
175 return false;
176 }
177
178 if sub_type.is_non_null() {
179 return self.is_subtype(sub_type.of_type(), super_type);
181 }
182
183 if super_type.is_list_type() {
185 if sub_type.is_list_type() {
186 return self.is_subtype(sub_type.of_type(), super_type.of_type());
187 }
188
189 return false;
190 }
191
192 if sub_type.is_list_type() {
193 return false;
195 }
196
197 if let (Some(sub_type), Some(super_type)) = (
200 self.type_by_name(sub_type.inner_type()),
201 self.type_by_name(super_type.inner_type()),
202 ) {
203 return super_type.is_abstract_type()
204 && (sub_type.is_interface_type() || sub_type.is_object_type())
205 && self.is_possible_type(super_type, sub_type);
206 }
207
208 false
209 }
210}
211
212impl Type {
213 pub fn inner_type(&self) -> &str {
214 match self {
215 Type::NamedType(name) => name.as_str(),
216 Type::ListType(child) => child.inner_type(),
217 Type::NonNullType(child) => child.inner_type(),
218 }
219 }
220
221 fn of_type(&self) -> &Type {
222 match self {
223 Type::ListType(child) => child,
224 Type::NonNullType(child) => child,
225 Type::NamedType(_) => self,
226 }
227 }
228
229 pub fn is_non_null(&self) -> bool {
230 matches!(self, Type::NonNullType(_))
231 }
232
233 fn is_list_type(&self) -> bool {
234 matches!(self, Type::ListType(_))
235 }
236
237 pub fn is_named_type(&self) -> bool {
238 matches!(self, Type::NamedType(_))
239 }
240}
241
242impl Value {
243 pub fn compare(&self, other: &Self) -> bool {
244 match (self, other) {
245 (Value::Null, Value::Null) => true,
246 (Value::Boolean(a), Value::Boolean(b)) => a == b,
247 (Value::Int(a), Value::Int(b)) => a == b,
248 (Value::Float(a), Value::Float(b)) => a == b,
249 (Value::String(a), Value::String(b)) => a.eq(b),
250 (Value::Enum(a), Value::Enum(b)) => a.eq(b),
251 (Value::List(a), Value::List(b)) => a.iter().zip(b.iter()).all(|(a, b)| a.compare(b)),
252 (Value::Object(a), Value::Object(b)) => {
253 if a.len() != b.len() {
254 return false;
255 }
256 let mut matched = vec![false; b.len()];
257 for (k_a, v_a) in a.iter() {
258 let found = b
259 .iter()
260 .enumerate()
261 .find(|(idx, (k_b, v_b))| !matched[*idx] && k_a == k_b && v_a.compare(v_b));
262 match found {
263 Some((idx, _)) => matched[idx] = true,
264 None => return false,
265 }
266 }
267 true
268 }
269 (Value::Variable(a), Value::Variable(b)) => a.eq(b),
270 _ => false,
271 }
272 }
273
274 pub fn variables_in_use(&self) -> Vec<&str> {
275 match self {
276 Value::Variable(v) => vec![v],
277 Value::List(list) => list.iter().flat_map(|v| v.variables_in_use()).collect(),
278 Value::Object(object) => object
279 .iter()
280 .flat_map(|(_, v)| v.variables_in_use())
281 .collect(),
282 _ => vec![],
283 }
284 }
285}
286
287impl InputValue {
288 pub fn is_required(&self) -> bool {
289 if let Type::NonNullType(_inner_type) = &self.value_type {
290 if self.default_value.is_none() {
291 return true;
292 }
293 }
294
295 false
296 }
297}
298
299impl TypeDefinition {
300 fn interfaces(&self) -> Vec<String> {
301 match self {
302 schema::TypeDefinition::Object(o) => o.interfaces(),
303 schema::TypeDefinition::Interface(i) => i.interfaces(),
304 _ => vec![],
305 }
306 }
307
308 pub fn has_sub_type(&self, other_type: &TypeDefinition) -> bool {
309 match self {
310 TypeDefinition::Interface(interface_type) => {
311 interface_type.is_implemented_by(other_type)
312 }
313 TypeDefinition::Union(union_type) => union_type.has_sub_type(other_type.name()),
314 _ => false,
315 }
316 }
317
318 pub fn has_concrete_sub_type(&self, concrete_type: &TypeDefinition) -> bool {
319 match self {
320 TypeDefinition::Interface(interface_type) => {
321 interface_type.is_implemented_by(concrete_type)
322 }
323 TypeDefinition::Union(union_type) => union_type.has_sub_type(concrete_type.name()),
324 _ => false,
325 }
326 }
327}
328
329impl TypeDefinition {
330 pub fn possible_types<'a>(&self, schema: &'a schema::Document) -> Vec<&'a TypeDefinition> {
331 match self {
332 TypeDefinition::Object(_) => vec![],
333 TypeDefinition::InputObject(_) => vec![],
334 TypeDefinition::Enum(_) => vec![],
335 TypeDefinition::Scalar(_) => vec![],
336 TypeDefinition::Interface(i) => schema
337 .type_map()
338 .values()
339 .filter_map(|type_def| {
340 if i.is_implemented_by(type_def) {
341 return Some(*type_def);
342 }
343
344 None
345 })
346 .collect(),
347 TypeDefinition::Union(u) => u
348 .types
349 .iter()
350 .filter_map(|type_name| {
351 if let Some(type_def) = schema.type_by_name(type_name) {
352 return Some(type_def);
353 }
354
355 None
356 })
357 .collect(),
358 }
359 }
360}
361
362impl InterfaceType {
363 fn interfaces(&self) -> Vec<String> {
364 self.implements_interfaces.clone()
365 }
366
367 pub fn has_sub_type(&self, other_type: &TypeDefinition) -> bool {
368 self.is_implemented_by(other_type)
369 }
370
371 pub fn has_concrete_sub_type(&self, concrete_type: &TypeDefinition) -> bool {
372 self.is_implemented_by(concrete_type)
373 }
374}
375
376impl ObjectType {
377 fn interfaces(&self) -> Vec<String> {
378 self.implements_interfaces.clone()
379 }
380
381 pub fn has_sub_type(&self, _other_type: &TypeDefinition) -> bool {
382 false
383 }
384
385 pub fn has_concrete_sub_type(&self, _concrete_type: &ObjectType) -> bool {
386 false
387 }
388}
389
390impl UnionType {
391 pub fn has_sub_type(&self, other_type_name: &str) -> bool {
392 self.types.iter().any(|v| other_type_name.eq(v))
393 }
394}
395
396impl InterfaceType {
397 pub fn is_implemented_by(&self, other_type: &TypeDefinition) -> bool {
398 other_type.interfaces().iter().any(|v| self.name.eq(v))
399 }
400}
401
402impl schema::TypeDefinition {
403 pub fn name(&self) -> &str {
404 match self {
405 schema::TypeDefinition::Object(o) => &o.name,
406 schema::TypeDefinition::Interface(i) => &i.name,
407 schema::TypeDefinition::Union(u) => &u.name,
408 schema::TypeDefinition::Scalar(s) => &s.name,
409 schema::TypeDefinition::Enum(e) => &e.name,
410 schema::TypeDefinition::InputObject(i) => &i.name,
411 }
412 }
413
414 pub fn is_abstract_type(&self) -> bool {
415 matches!(
416 self,
417 schema::TypeDefinition::Interface(_) | schema::TypeDefinition::Union(_)
418 )
419 }
420
421 fn is_interface_type(&self) -> bool {
422 matches!(self, schema::TypeDefinition::Interface(_))
423 }
424
425 pub fn is_leaf_type(&self) -> bool {
426 matches!(
427 self,
428 schema::TypeDefinition::Scalar(_) | schema::TypeDefinition::Enum(_)
429 )
430 }
431
432 pub fn is_input_type(&self) -> bool {
433 matches!(
434 self,
435 schema::TypeDefinition::Scalar(_)
436 | schema::TypeDefinition::Enum(_)
437 | schema::TypeDefinition::InputObject(_)
438 )
439 }
440
441 pub fn is_composite_type(&self) -> bool {
442 matches!(
443 self,
444 schema::TypeDefinition::Object(_)
445 | schema::TypeDefinition::Interface(_)
446 | schema::TypeDefinition::Union(_)
447 )
448 }
449
450 pub fn is_object_type(&self) -> bool {
451 matches!(self, schema::TypeDefinition::Object(_o))
452 }
453
454 pub fn is_union_type(&self) -> bool {
455 matches!(self, schema::TypeDefinition::Union(_o))
456 }
457
458 pub fn is_enum_type(&self) -> bool {
459 matches!(self, schema::TypeDefinition::Enum(_o))
460 }
461
462 pub fn is_scalar_type(&self) -> bool {
463 matches!(self, schema::TypeDefinition::Scalar(_o))
464 }
465}
466
467pub trait AstNodeWithName {
468 fn node_name(&self) -> Option<&str>;
469}
470
471impl AstNodeWithName for query::OperationDefinition {
472 fn node_name(&self) -> Option<&str> {
473 match self {
474 query::OperationDefinition::Query(q) => q.name.as_deref(),
475 query::OperationDefinition::SelectionSet(_s) => None,
476 query::OperationDefinition::Mutation(m) => m.name.as_deref(),
477 query::OperationDefinition::Subscription(s) => s.name.as_deref(),
478 }
479 }
480}
481
482impl AstNodeWithName for query::FragmentDefinition {
483 fn node_name(&self) -> Option<&str> {
484 Some(&self.name)
485 }
486}
487
488impl AstNodeWithName for query::FragmentSpread {
489 fn node_name(&self) -> Option<&str> {
490 Some(&self.fragment_name)
491 }
492}
493
494impl query::SelectionSet {
495 pub fn get_recursive_fragment_spreads(&self) -> Vec<&FragmentSpread> {
496 self.items
497 .iter()
498 .flat_map(|v| match v {
499 query::Selection::FragmentSpread(f) => vec![f],
500 query::Selection::Field(f) => f.selection_set.get_fragment_spreads(),
501 query::Selection::InlineFragment(f) => f.selection_set.get_fragment_spreads(),
502 })
503 .collect()
504 }
505
506 fn get_fragment_spreads(&self) -> Vec<&FragmentSpread> {
507 self.items
508 .iter()
509 .flat_map(|v| match v {
510 query::Selection::FragmentSpread(f) => vec![f],
511 _ => vec![],
512 })
513 .collect()
514 }
515}
516
517impl query::Selection {
518 pub fn directives(&self) -> &[Directive] {
519 match self {
520 query::Selection::Field(f) => &f.directives,
521 query::Selection::FragmentSpread(f) => &f.directives,
522 query::Selection::InlineFragment(f) => &f.directives,
523 }
524 }
525 pub fn selection_set(&self) -> Option<&SelectionSet> {
526 match self {
527 query::Selection::Field(f) => Some(&f.selection_set),
528 query::Selection::FragmentSpread(_) => None,
529 query::Selection::InlineFragment(f) => Some(&f.selection_set),
530 }
531 }
532}
533
534impl schema::Definition<'static, String> {
535 pub fn name(&self) -> Option<&str> {
536 match self {
537 schema::Definition::SchemaDefinition(_) => None,
538 schema::Definition::TypeDefinition(type_def) => Some(type_def.name()),
539 schema::Definition::TypeExtension(type_ext) => Some(type_ext.name()),
540 schema::Definition::DirectiveDefinition(directive_def) => Some(&directive_def.name),
541 }
542 }
543 pub fn fields<'a>(&'a self) -> Option<TypeDefinitionFields<'a>> {
544 match self {
545 schema::Definition::SchemaDefinition(_) => None,
546 schema::Definition::TypeDefinition(type_def) => type_def.fields(),
547 schema::Definition::TypeExtension(type_ext) => type_ext.fields(),
548 schema::Definition::DirectiveDefinition(_) => None,
549 }
550 }
551 pub fn directives(&self) -> Option<&[Directive]> {
552 match self {
553 schema::Definition::SchemaDefinition(schema_def) => Some(&schema_def.directives),
554 schema::Definition::TypeDefinition(type_def) => type_def.directives(),
555 schema::Definition::TypeExtension(type_ext) => type_ext.directives(),
556 schema::Definition::DirectiveDefinition(_) => None,
557 }
558 }
559}
560
561pub enum TypeDefinitionFields<'a> {
562 Fields(&'a [Field]),
563 InputValues(&'a [InputValue]),
564 EnumValues(&'a [EnumValue]),
565}
566
567impl TypeDefinition {
568 pub fn fields<'a>(&'a self) -> Option<TypeDefinitionFields<'a>> {
569 match self {
570 TypeDefinition::Scalar(_) => None,
571 TypeDefinition::Object(object) => Some(TypeDefinitionFields::Fields(&object.fields)),
572 TypeDefinition::Interface(interface) => {
573 Some(TypeDefinitionFields::Fields(&interface.fields))
574 }
575 TypeDefinition::Union(_) => None,
576 TypeDefinition::Enum(enum_) => Some(TypeDefinitionFields::EnumValues(&enum_.values)),
577 TypeDefinition::InputObject(input_object) => {
578 Some(TypeDefinitionFields::InputValues(&input_object.fields))
579 }
580 }
581 }
582 pub fn directives(&self) -> Option<&[Directive]> {
583 match self {
584 TypeDefinition::Scalar(_) => None,
585 TypeDefinition::Object(object) => Some(&object.directives),
586 TypeDefinition::Interface(interface) => Some(&interface.directives),
587 TypeDefinition::Union(union) => Some(&union.directives),
588 TypeDefinition::Enum(enum_) => Some(&enum_.directives),
589 TypeDefinition::InputObject(input_object) => Some(&input_object.directives),
590 }
591 }
592}
593
594impl TypeExtension<'static, String> {
595 pub fn name(&self) -> &str {
596 match self {
597 TypeExtension::Object(object) => &object.name,
598 TypeExtension::Interface(interface) => &interface.name,
599 TypeExtension::Union(union) => &union.name,
600 TypeExtension::Scalar(scalar) => &scalar.name,
601 TypeExtension::Enum(enum_) => &enum_.name,
602 TypeExtension::InputObject(input_object) => &input_object.name,
603 }
604 }
605 pub fn fields<'a>(&'a self) -> Option<TypeDefinitionFields<'a>> {
606 match self {
607 TypeExtension::Object(object) => Some(TypeDefinitionFields::Fields(&object.fields)),
608 TypeExtension::Interface(interface) => {
609 Some(TypeDefinitionFields::Fields(&interface.fields))
610 }
611 _ => None,
612 }
613 }
614 pub fn directives(&self) -> Option<&[Directive]> {
615 match self {
616 TypeExtension::Object(object) => Some(&object.directives),
617 TypeExtension::Interface(interface) => Some(&interface.directives),
618 TypeExtension::Union(union) => Some(&union.directives),
619 TypeExtension::Enum(enum_) => Some(&enum_.directives),
620 TypeExtension::InputObject(input_object) => Some(&input_object.directives),
621 TypeExtension::Scalar(scalar) => Some(&scalar.directives),
622 }
623 }
624}