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