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