1use crate::ast::{ASTContext, DefaultIn, NamedType, OperationKind, Type};
2use bumpalo::collections::Vec;
3use bumpalo::Bump;
4use hashbrown::hash_map::DefaultHashBuilder;
5use hashbrown::{HashMap, HashSet};
6
7#[derive(Debug, Clone, PartialEq)]
14pub struct Schema<'a> {
15 pub(crate) query_type: Option<&'a SchemaObject<'a>>,
16 pub(crate) mutation_type: Option<&'a SchemaObject<'a>>,
17 pub(crate) subscription_type: Option<&'a SchemaObject<'a>>,
18 pub(crate) types:
19 hashbrown::HashMap<&'a str, &'a SchemaType<'a>, DefaultHashBuilder, &'a bumpalo::Bump>,
20}
21
22impl<'a> DefaultIn<'a> for Schema<'a> {
23 fn default_in(arena: &'a Bump) -> Self {
24 Schema {
25 query_type: None,
26 mutation_type: None,
27 subscription_type: None,
28 types: HashMap::new_in(arena),
29 }
30 }
31}
32
33impl<'a> Schema<'a> {
34 pub fn is_empty(&self) -> bool {
36 self.types.is_empty()
37 && self.query_type.is_none()
38 && self.mutation_type.is_none()
39 && self.subscription_type.is_none()
40 }
41
42 #[inline]
44 pub fn query_type(&self) -> Option<&'a SchemaObject<'a>> {
45 self.query_type
46 }
47
48 #[inline]
50 pub fn mutation_type(&self) -> Option<&'a SchemaObject<'a>> {
51 self.mutation_type
52 }
53
54 #[inline]
56 pub fn subscription_type(&self) -> Option<&'a SchemaObject<'a>> {
57 self.subscription_type
58 }
59
60 #[inline]
62 pub fn get_root_type(&self, operation_kind: OperationKind) -> Option<&'a SchemaObject<'a>> {
63 match operation_kind {
64 OperationKind::Query => self.query_type,
65 OperationKind::Mutation => self.mutation_type,
66 OperationKind::Subscription => self.subscription_type,
67 }
68 }
69
70 #[inline]
72 pub fn get_type(&self, name: &'a str) -> Option<&'a SchemaType<'a>> {
73 self.types.get(name).copied()
74 }
75
76 pub fn is_sub_type(&self, abstract_type: SchemaType<'a>, sub_type: SchemaType<'a>) -> bool {
81 match abstract_type {
82 SchemaType::Union(schema_union) => schema_union.is_sub_type(sub_type),
83 SchemaType::Interface(schema_interface) => schema_interface.is_sub_type(sub_type),
84 SchemaType::Object(schema_object) => {
85 if let SchemaType::Object(sub_object_type) = sub_type {
86 sub_object_type == schema_object
87 } else {
88 false
89 }
90 }
91 _ => false,
92 }
93 }
94}
95
96pub trait SchemaFields<'a>: Sized {
98 fn add_field(&mut self, ctx: &'a ASTContext, field: SchemaField<'a>);
100
101 fn get_fields(
103 &self,
104 ) -> HashMap<&'a str, &'a SchemaField<'a>, DefaultHashBuilder, &'a bumpalo::Bump>;
105
106 fn get_field(&self, name: &'a str) -> Option<&'a SchemaField<'a>> {
108 self.get_fields().get(name).copied()
109 }
110}
111
112pub trait SchemaInterfaces<'a>: Sized {
114 fn add_interface(&mut self, ctx: &'a ASTContext, interface: &'a str);
116
117 fn get_interfaces(&self) -> Vec<'a, &'a str>;
119
120 #[inline]
122 fn implements_interface(&self, schema_interface: &SchemaInterface<'a>) -> bool {
123 self.get_interfaces()
124 .into_iter()
125 .any(|interface| interface == schema_interface.name)
126 }
127}
128
129pub trait SchemaPossibleTypes<'a>: Sized {
131 fn add_possible_type(&mut self, ctx: &'a ASTContext, object: &'a str);
133
134 fn get_possible_types(&self) -> Vec<'a, &'a str>;
136
137 #[inline]
139 fn get_possible_type(&self, name: &'a str) -> Option<&'a str> {
140 self.get_possible_types()
141 .into_iter()
142 .find(|&possible_type| possible_type == name)
143 }
144
145 #[inline]
147 fn is_possible_type(&self, schema_object: &SchemaObject<'a>) -> bool {
148 self.get_possible_types()
149 .into_iter()
150 .any(|possible_type| possible_type == schema_object.name)
151 }
152}
153
154pub trait SchemaSuperType<'a>: Sized {
156 fn is_sub_type(&self, subtype: SchemaType<'a>) -> bool;
158}
159
160#[derive(Debug, Clone, PartialEq)]
165pub struct SchemaObject<'a> {
166 pub name: &'a str,
167 pub(crate) fields: HashMap<&'a str, &'a SchemaField<'a>, DefaultHashBuilder, &'a bumpalo::Bump>,
168 pub(crate) interfaces: Vec<'a, &'a str>,
169}
170
171impl<'a> SchemaObject<'a> {
172 #[inline]
173 pub fn new(ctx: &'a ASTContext, name: &'a str) -> Self {
174 SchemaObject {
175 name,
176 fields: HashMap::new_in(&ctx.arena),
177 interfaces: Vec::new_in(&ctx.arena),
178 }
179 }
180}
181
182impl<'a> SchemaFields<'a> for SchemaObject<'a> {
183 fn add_field(&mut self, ctx: &'a ASTContext, field: SchemaField<'a>) {
185 self.fields.insert(field.name, ctx.alloc(field));
186 }
187
188 fn get_fields(
190 &self,
191 ) -> HashMap<&'a str, &'a SchemaField<'a>, DefaultHashBuilder, &'a bumpalo::Bump> {
192 self.fields.clone()
193 }
194}
195
196impl<'a> SchemaInterfaces<'a> for SchemaObject<'a> {
197 fn add_interface(&mut self, _ctx: &'a ASTContext, interface: &'a str) {
199 self.interfaces.push(interface);
201 }
202
203 #[inline]
205 fn get_interfaces(&self) -> Vec<'a, &'a str> {
206 self.interfaces.clone()
207 }
208}
209
210#[derive(Clone, Debug)]
217pub struct SchemaInterface<'a> {
218 pub name: &'a str,
219 pub(crate) fields: HashMap<&'a str, &'a SchemaField<'a>, DefaultHashBuilder, &'a bumpalo::Bump>,
220 pub(crate) interfaces: Vec<'a, &'a str>,
221 pub(crate) possible_interfaces: Vec<'a, &'a str>,
222 pub(crate) possible_types: Vec<'a, &'a str>,
223}
224
225impl<'a> PartialEq for SchemaInterface<'a> {
226 fn eq(&self, other: &Self) -> bool {
227 self.name == other.name
228 && maps_are_equal(self.fields.clone(), other.fields.clone())
229 && self.interfaces == other.interfaces
230 && self.possible_interfaces == other.possible_interfaces
231 && self.possible_types == other.possible_types
232 }
233}
234
235impl<'a> SchemaInterface<'a> {
236 #[inline]
237 pub fn new(ctx: &'a ASTContext, name: &'a str) -> Self {
238 SchemaInterface {
239 name,
240 fields: HashMap::new_in(&ctx.arena),
241 interfaces: Vec::new_in(&ctx.arena),
242 possible_interfaces: Vec::new_in(&ctx.arena),
243 possible_types: Vec::new_in(&ctx.arena),
244 }
245 }
246
247 pub fn add_possible_interface(&mut self, _ctx: &'a ASTContext, interface: &'a str) {
249 self.possible_interfaces.push(interface);
250 }
251
252 #[inline]
254 pub fn get_possible_interfaces(&self) -> Vec<'a, &'a str> {
255 self.possible_interfaces.clone()
256 }
257}
258
259impl<'a> SchemaFields<'a> for SchemaInterface<'a> {
260 fn add_field(&mut self, ctx: &'a ASTContext, field: SchemaField<'a>) {
262 self.fields.insert(field.name, ctx.alloc(field));
263 }
264
265 fn get_fields(
267 &self,
268 ) -> HashMap<&'a str, &'a SchemaField<'a>, DefaultHashBuilder, &'a bumpalo::Bump> {
269 self.fields.clone()
270 }
271}
272
273impl<'a> SchemaInterfaces<'a> for SchemaInterface<'a> {
274 fn add_interface(&mut self, _ctx: &'a ASTContext, interface: &'a str) {
276 self.interfaces.push(interface);
277 }
278
279 #[inline]
281 fn get_interfaces(&self) -> Vec<'a, &'a str> {
282 self.interfaces.clone()
283 }
284}
285
286impl<'a> SchemaPossibleTypes<'a> for SchemaInterface<'a> {
287 fn add_possible_type(&mut self, _ctx: &'a ASTContext, object: &'a str) {
289 self.possible_types.push(object);
290 }
291
292 #[inline]
294 fn get_possible_types(&self) -> Vec<'a, &'a str> {
295 self.possible_types.clone()
296 }
297}
298
299impl<'a> SchemaSuperType<'a> for SchemaInterface<'a> {
300 #[inline]
301 fn is_sub_type(&self, sub_type: SchemaType<'a>) -> bool {
302 match sub_type {
303 SchemaType::Object(schema_object) => schema_object.implements_interface(self),
304 SchemaType::Interface(schema_interface) => schema_interface.implements_interface(self),
305 _ => false,
306 }
307 }
308}
309
310#[derive(Debug, Clone, PartialEq)]
315pub struct SchemaField<'a> {
316 pub name: &'a str,
317 pub arguments: HashMap<&'a str, SchemaInputField<'a>, DefaultHashBuilder, &'a bumpalo::Bump>,
318 pub output_type: &'a TypeRef<'a>,
319}
320
321impl<'a> SchemaField<'a> {
322 #[inline]
323 pub fn new(ctx: &'a ASTContext, name: &'a str, output_type: &'a TypeRef<'a>) -> Self {
324 SchemaField {
325 name,
326 arguments: HashMap::new_in(&ctx.arena),
327 output_type,
328 }
329 }
330
331 pub fn add_argument(&mut self, _ctx: &'a ASTContext, arg: SchemaInputField<'a>) {
332 self.arguments.insert(arg.name, arg);
333 }
334
335 #[inline]
336 pub fn get_argument(&self, name: &'a str) -> Option<&SchemaInputField<'a>> {
337 self.arguments.get(name)
338 }
339}
340
341#[derive(Debug, Clone)]
347pub struct SchemaUnion<'a> {
348 pub name: &'a str,
349 possible_types: Vec<'a, &'a str>,
350}
351
352impl<'a> PartialEq for SchemaUnion<'a> {
353 fn eq(&self, other: &Self) -> bool {
354 self.name == other.name && self.possible_types == other.possible_types
355 }
356}
357
358impl<'a> SchemaUnion<'a> {
359 #[inline]
360 pub fn new(ctx: &'a ASTContext, name: &'a str) -> Self {
361 SchemaUnion {
362 name,
363 possible_types: Vec::new_in(&ctx.arena),
364 }
365 }
366
367 #[inline]
368 pub fn is_sub_type(&self, sub_type: SchemaType<'a>) -> bool {
369 match sub_type {
370 SchemaType::Object(schema_object) => self
371 .possible_types
372 .iter()
373 .any(|possible| possible == &schema_object.name),
374 _ => false,
375 }
376 }
377}
378
379impl<'a> SchemaPossibleTypes<'a> for SchemaUnion<'a> {
380 fn add_possible_type(&mut self, _ctx: &'a ASTContext, object: &'a str) {
382 self.possible_types.push(object);
383 }
384
385 #[inline]
387 fn get_possible_types(&self) -> Vec<'a, &'a str> {
388 self.possible_types.clone()
389 }
390}
391
392impl<'a> SchemaSuperType<'a> for SchemaUnion<'a> {
393 #[inline]
394 fn is_sub_type(&self, sub_type: SchemaType<'a>) -> bool {
395 if let SchemaType::Object(schema_object) = sub_type {
396 self.is_possible_type(schema_object)
397 } else {
398 false
399 }
400 }
401}
402
403#[derive(Debug, Clone, PartialEq)]
410pub struct SchemaScalar<'a> {
411 pub name: &'a str,
412}
413
414impl<'a> SchemaScalar<'a> {
415 #[inline]
416 pub fn new(name: &'a str) -> Self {
417 SchemaScalar { name }
418 }
419}
420
421#[derive(Debug, PartialEq, Clone)]
422pub struct SchemaEnum<'a> {
423 pub name: &'a str,
424 pub values: HashSet<&'a str, DefaultHashBuilder, &'a bumpalo::Bump>,
425}
426
427impl<'a> SchemaEnum<'a> {
428 #[inline]
429 pub fn new(ctx: &'a ASTContext, name: &'a str) -> Self {
430 SchemaEnum {
431 name,
432 values: HashSet::new_in(&ctx.arena),
433 }
434 }
435
436 pub fn add_value(&mut self, _ctx: &'a ASTContext, value: &'a str) {
437 self.values.insert(value);
438 }
439}
440
441#[derive(Debug, Clone, PartialEq)]
447pub struct SchemaInputObject<'a> {
448 pub name: &'a str,
449 pub fields: HashMap<&'a str, SchemaInputField<'a>, DefaultHashBuilder, &'a bumpalo::Bump>,
450}
451
452impl<'a> SchemaInputObject<'a> {
453 #[inline]
454 pub fn new(ctx: &'a ASTContext, name: &'a str) -> Self {
455 SchemaInputObject {
456 name,
457 fields: HashMap::new_in(&ctx.arena),
458 }
459 }
460
461 pub fn add_field(&mut self, _ctx: &'a ASTContext, field: SchemaInputField<'a>) {
462 self.fields.insert(field.name, field);
463 }
464}
465
466#[derive(Debug, PartialEq, Clone, Copy)]
467pub struct SchemaInputField<'a> {
468 pub name: &'a str,
469 pub input_type: &'a TypeRef<'a>,
470}
471
472impl<'a> SchemaInputField<'a> {
473 #[inline]
474 pub fn new(name: &'a str, input_type: &'a TypeRef<'a>) -> Self {
475 SchemaInputField { name, input_type }
476 }
477}
478
479#[derive(Debug, PartialEq, Clone, Copy)]
483pub enum SchemaType<'a> {
484 InputObject(&'a SchemaInputObject<'a>),
485 Object(&'a SchemaObject<'a>),
486 Union(&'a SchemaUnion<'a>),
487 Interface(&'a SchemaInterface<'a>),
488 Scalar(&'a SchemaScalar<'a>),
489 Enum(&'a SchemaEnum<'a>),
490}
491
492impl<'a> SchemaType<'a> {
493 #[inline]
494 pub fn name(&self) -> &'a str {
495 match self {
496 SchemaType::InputObject(x) => x.name,
497 SchemaType::Object(x) => x.name,
498 SchemaType::Union(x) => x.name,
499 SchemaType::Interface(x) => x.name,
500 SchemaType::Scalar(x) => x.name,
501 SchemaType::Enum(x) => x.name,
502 }
503 }
504
505 pub fn object(&self) -> Option<&'a SchemaObject<'a>> {
506 match self {
507 SchemaType::Object(x) => Some(x),
508 _ => None,
509 }
510 }
511
512 pub fn input_object(&self) -> Option<&'a SchemaInputObject<'a>> {
513 match self {
514 SchemaType::InputObject(x) => Some(x),
515 _ => None,
516 }
517 }
518
519 pub fn interface(&self) -> Option<&'a SchemaInterface<'a>> {
520 match self {
521 SchemaType::Interface(x) => Some(x),
522 _ => None,
523 }
524 }
525
526 pub fn union_type(&self) -> Option<&'a SchemaUnion<'a>> {
527 match self {
528 SchemaType::Union(x) => Some(x),
529 _ => None,
530 }
531 }
532
533 pub fn input_type(&self) -> Option<InputType<'a>> {
534 match self {
535 SchemaType::Scalar(x) => Some(InputType::Scalar(x)),
536 SchemaType::Enum(x) => Some(InputType::Enum(x)),
537 SchemaType::InputObject(x) => Some(InputType::InputObject(x)),
538 _ => None,
539 }
540 }
541
542 pub fn output_type(&self) -> Option<OutputType<'a>> {
543 match self {
544 SchemaType::Object(x) => Some(OutputType::Object(x)),
545 SchemaType::Union(x) => Some(OutputType::Union(x)),
546 SchemaType::Interface(x) => Some(OutputType::Interface(x)),
547 SchemaType::Scalar(x) => Some(OutputType::Scalar(x)),
548 SchemaType::Enum(x) => Some(OutputType::Enum(x)),
549 _ => None,
550 }
551 }
552}
553
554#[derive(Debug, PartialEq, Clone)]
555pub enum OwnedSchemaType<'a> {
556 InputObject(SchemaInputObject<'a>),
557 Object(SchemaObject<'a>),
558 Union(SchemaUnion<'a>),
559 Interface(SchemaInterface<'a>),
560 Scalar(SchemaScalar<'a>),
561 Enum(SchemaEnum<'a>),
562}
563
564impl<'a> OwnedSchemaType<'a> {
565 #[inline]
566 pub fn name(&self) -> &'a str {
567 match self {
568 OwnedSchemaType::InputObject(x) => x.name,
569 OwnedSchemaType::Object(x) => x.name,
570 OwnedSchemaType::Union(x) => x.name,
571 OwnedSchemaType::Interface(x) => x.name,
572 OwnedSchemaType::Scalar(x) => x.name,
573 OwnedSchemaType::Enum(x) => x.name,
574 }
575 }
576
577 pub fn object(&'a self) -> Option<&'a SchemaObject<'a>> {
578 match self {
579 OwnedSchemaType::Object(x) => Some(x),
580 _ => None,
581 }
582 }
583
584 pub fn input_object(&'a self) -> Option<&'a SchemaInputObject<'a>> {
585 match self {
586 OwnedSchemaType::InputObject(x) => Some(x),
587 _ => None,
588 }
589 }
590
591 pub fn interface(&'a self) -> Option<&'a SchemaInterface<'a>> {
592 match self {
593 OwnedSchemaType::Interface(x) => Some(x),
594 _ => None,
595 }
596 }
597
598 pub fn union_type(&'a self) -> Option<&'a SchemaUnion<'a>> {
599 match self {
600 OwnedSchemaType::Union(x) => Some(x),
601 _ => None,
602 }
603 }
604
605 pub fn input_type(&'a self) -> Option<InputType<'a>> {
606 match self {
607 OwnedSchemaType::Scalar(x) => Some(InputType::Scalar(x)),
608 OwnedSchemaType::Enum(x) => Some(InputType::Enum(x)),
609 OwnedSchemaType::InputObject(x) => Some(InputType::InputObject(x)),
610 _ => None,
611 }
612 }
613
614 pub fn output_type(&'a self) -> Option<OutputType<'a>> {
615 match self {
616 OwnedSchemaType::Object(x) => Some(OutputType::Object(x)),
617 OwnedSchemaType::Union(x) => Some(OutputType::Union(x)),
618 OwnedSchemaType::Interface(x) => Some(OutputType::Interface(x)),
619 OwnedSchemaType::Scalar(x) => Some(OutputType::Scalar(x)),
620 OwnedSchemaType::Enum(x) => Some(OutputType::Enum(x)),
621 _ => None,
622 }
623 }
624}
625
626impl<'a> From<&'a SchemaObject<'a>> for SchemaType<'a> {
627 #[inline]
628 fn from(schema_object: &'a SchemaObject<'a>) -> Self {
629 SchemaType::Object(schema_object)
630 }
631}
632
633impl<'a> From<&'a SchemaUnion<'a>> for SchemaType<'a> {
634 #[inline]
635 fn from(schema_union: &'a SchemaUnion<'a>) -> Self {
636 SchemaType::Union(schema_union)
637 }
638}
639
640impl<'a> From<&'a SchemaInterface<'a>> for SchemaType<'a> {
641 #[inline]
642 fn from(schema_interface: &'a SchemaInterface<'a>) -> Self {
643 SchemaType::Interface(schema_interface)
644 }
645}
646
647impl<'a> From<OutputType<'a>> for SchemaType<'a> {
648 #[inline]
649 fn from(type_ref: OutputType<'a>) -> Self {
650 match type_ref {
651 OutputType::Object(x) => SchemaType::Object(x),
652 OutputType::Union(x) => SchemaType::Union(x),
653 OutputType::Interface(x) => SchemaType::Interface(x),
654 OutputType::Scalar(x) => SchemaType::Scalar(x),
655 OutputType::Enum(x) => SchemaType::Enum(x),
656 }
657 }
658}
659
660impl<'a> From<InputType<'a>> for SchemaType<'a> {
661 #[inline]
662 fn from(type_ref: InputType<'a>) -> Self {
663 match type_ref {
664 InputType::InputObject(x) => SchemaType::InputObject(x),
665 InputType::Scalar(x) => SchemaType::Scalar(x),
666 InputType::Enum(x) => SchemaType::Enum(x),
667 }
668 }
669}
670
671#[derive(Debug, PartialEq, Clone, Copy)]
676pub enum OutputType<'a> {
677 Object(&'a SchemaObject<'a>),
678 Union(&'a SchemaUnion<'a>),
679 Interface(&'a SchemaInterface<'a>),
680 Scalar(&'a SchemaScalar<'a>),
681 Enum(&'a SchemaEnum<'a>),
682}
683
684impl<'a> OutputType<'a> {
685 #[inline]
686 pub fn name(&self) -> &str {
687 match self {
688 OutputType::Object(x) => x.name,
689 OutputType::Union(x) => x.name,
690 OutputType::Interface(x) => x.name,
691 OutputType::Scalar(x) => x.name,
692 OutputType::Enum(x) => x.name,
693 }
694 }
695
696 #[inline]
697 pub fn into_schema_type(&self) -> SchemaType<'a> {
698 match self {
699 OutputType::Object(x) => SchemaType::Object(x),
700 OutputType::Union(x) => SchemaType::Union(x),
701 OutputType::Interface(x) => SchemaType::Interface(x),
702 OutputType::Scalar(x) => SchemaType::Scalar(x),
703 OutputType::Enum(x) => SchemaType::Enum(x),
704 }
705 }
706}
707
708#[derive(Debug, PartialEq, Clone, Copy)]
713pub enum InputType<'a> {
714 InputObject(&'a SchemaInputObject<'a>),
715 Scalar(&'a SchemaScalar<'a>),
716 Enum(&'a SchemaEnum<'a>),
717}
718
719impl<'a> InputType<'a> {
720 #[inline]
721 pub fn name(&self) -> &str {
722 match self {
723 InputType::InputObject(o) => o.name,
724 InputType::Scalar(s) => s.name,
725 InputType::Enum(e) => e.name,
726 }
727 }
728
729 #[inline]
730 pub fn named_type(&self) -> SchemaType<'a> {
731 match self {
732 InputType::InputObject(x) => SchemaType::InputObject(x),
733 InputType::Scalar(x) => SchemaType::Scalar(x),
734 InputType::Enum(x) => SchemaType::Enum(x),
735 }
736 }
737}
738
739#[derive(Clone, Copy)]
740pub enum TypeRef<'a> {
741 Type(&'a str),
742 ListType(&'a TypeRef<'a>),
743 NonNullType(&'a TypeRef<'a>),
744}
745
746impl<'a> TypeRef<'a> {
747 #[inline]
748 pub fn of_type(&self, schema: &'a Schema<'a>) -> &'a SchemaType<'a> {
749 match self {
750 TypeRef::Type(of_type) => {
751 let schema_type = schema
752 .get_type(of_type)
753 .expect("Referenced type should exist in the schema.");
754 schema_type
755 }
756 TypeRef::ListType(of_type) => of_type.of_type(schema),
757 TypeRef::NonNullType(of_type) => of_type.of_type(schema),
758 }
759 }
760}
761
762impl<'a> std::fmt::Debug for TypeRef<'a> {
765 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
766 match self {
767 Self::Type(arg0) => f.debug_tuple("OutputTypeRef").field(&arg0).finish(),
768 Self::ListType(arg0) => f.debug_tuple("ListType").field(arg0).finish(),
769 Self::NonNullType(arg0) => f.debug_tuple("NonNullType").field(arg0).finish(),
770 }
771 }
772}
773
774impl<'a> PartialEq for TypeRef<'a> {
778 fn eq(&self, other: &Self) -> bool {
779 match (self, other) {
780 (Self::Type(left), Self::Type(right)) => left == right,
781 (Self::ListType(left), Self::ListType(right)) => left == right,
782 (Self::NonNullType(left), Self::NonNullType(right)) => left == right,
783 _ => false,
784 }
785 }
786}
787
788fn maps_are_equal<'a, V>(
790 left: HashMap<&'a str, V, DefaultHashBuilder, &'a bumpalo::Bump>,
791 right: HashMap<&'a str, V, DefaultHashBuilder, &'a bumpalo::Bump>,
792) -> bool
793where
794 V: PartialEq + Copy,
795{
796 let length_matches = left.len() == right.len();
797
798 length_matches
800 && left.iter().all(|(k, left_val)| {
801 right
802 .get(k)
803 .map(|right_val| left_val == right_val)
804 .unwrap_or(false)
805 })
806}
807
808pub trait Named {
810 fn name(&self) -> &str;
811}
812
813impl<'a> Named for &'a SchemaInterface<'a> {
814 fn name(&self) -> &str {
815 self.name
816 }
817}
818
819impl<'a> Named for &'a SchemaObject<'a> {
820 fn name(&self) -> &str {
821 self.name
822 }
823}
824
825impl<'a> Named for &'a SchemaUnion<'a> {
826 fn name(&self) -> &str {
827 self.name
828 }
829}
830
831pub fn schema_type_to_type<'arena>(
832 ctx: &'arena ASTContext,
833 schema: &'arena Schema,
834 schema_type: TypeRef<'arena>,
835) -> Type<'arena> {
836 match schema_type {
837 t @ TypeRef::Type(_) => match t.of_type(schema).input_type().expect("input schema type") {
838 InputType::InputObject(SchemaInputObject { name, .. })
839 | InputType::Scalar(SchemaScalar { name, .. })
840 | InputType::Enum(SchemaEnum { name, .. }) => Type::NamedType(NamedType { name }),
841 },
842 TypeRef::ListType(t) => Type::ListType(ctx.alloc(schema_type_to_type(ctx, schema, *t))),
843 TypeRef::NonNullType(t) => {
844 Type::NonNullType(ctx.alloc(schema_type_to_type(ctx, schema, *t)))
845 }
846 }
847}