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