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