rusty_gql/types/
type_definition.rs

1use graphql_parser::schema::TypeDefinition as ParserTypeDefinition;
2
3use crate::{FieldType, GqlDirective, Schema};
4
5use super::{
6    enum_type::EnumType, input_object::InputObjectType, interface::InterfaceType,
7    object::ObjectType, scalar::ScalarType, union_type::UnionType,
8};
9
10#[derive(Debug, Clone)]
11pub enum TypeDefinition {
12    Scalar(ScalarType),
13    Object(ObjectType),
14    Interface(InterfaceType),
15    Union(UnionType),
16    Enum(EnumType),
17    InputObject(InputObjectType),
18}
19
20impl ToString for TypeDefinition {
21    fn to_string(&self) -> String {
22        match self {
23            TypeDefinition::Scalar(_) => "Scalar".to_string(),
24            TypeDefinition::Object(_) => "Object".to_string(),
25            TypeDefinition::Interface(_) => "Interface".to_string(),
26            TypeDefinition::Union(_) => "Union".to_string(),
27            TypeDefinition::Enum(_) => "Enum".to_string(),
28            TypeDefinition::InputObject(_) => "InputObject".to_string(),
29        }
30    }
31}
32
33impl TypeDefinition {
34    pub fn from_schema_type_def(ty_def: &ParserTypeDefinition<'_, String>) -> Self {
35        match ty_def {
36            ParserTypeDefinition::Scalar(v) => TypeDefinition::Scalar(ScalarType::from(v.clone())),
37            ParserTypeDefinition::Object(v) => TypeDefinition::Object(ObjectType::from(v.clone())),
38            ParserTypeDefinition::Interface(v) => {
39                TypeDefinition::Interface(InterfaceType::from(v.clone()))
40            }
41            ParserTypeDefinition::Union(v) => TypeDefinition::Union(UnionType::from(v.clone())),
42            ParserTypeDefinition::Enum(v) => TypeDefinition::Enum(EnumType::from(v.clone())),
43            ParserTypeDefinition::InputObject(v) => {
44                TypeDefinition::InputObject(InputObjectType::from(v.clone()))
45            }
46        }
47    }
48
49    pub fn name(&self) -> &str {
50        match self {
51            TypeDefinition::Scalar(scalar) => &scalar.name,
52            TypeDefinition::Object(obj) => &obj.name,
53            TypeDefinition::Interface(interface) => &interface.name,
54            TypeDefinition::Union(uni) => &uni.name,
55            TypeDefinition::Enum(enu) => &enu.name,
56            TypeDefinition::InputObject(input_object) => &input_object.name,
57        }
58    }
59
60    pub fn description(&self) -> &Option<String> {
61        match self {
62            TypeDefinition::Scalar(scalar) => &scalar.description,
63            TypeDefinition::Object(obj) => &obj.description,
64            TypeDefinition::Interface(interface) => &interface.description,
65            TypeDefinition::Union(uni) => &uni.description,
66            TypeDefinition::Enum(enu) => &enu.description,
67            TypeDefinition::InputObject(input_object) => &input_object.description,
68        }
69    }
70
71    pub fn fields(&self) -> Option<&Vec<FieldType>> {
72        match self {
73            TypeDefinition::Object(obj) => Some(&obj.fields),
74            TypeDefinition::Interface(interface) => Some(&interface.fields),
75            _ => None,
76        }
77    }
78
79    pub fn get_field_by_name(&self, name: &str) -> Option<&FieldType> {
80        self.fields()
81            .and_then(|fields| fields.iter().find(|f| f.name == name))
82    }
83
84    pub fn is_composite_type(&self) -> bool {
85        matches!(
86            self,
87            &TypeDefinition::Object(_) | &TypeDefinition::Interface(_) | &TypeDefinition::Union(_)
88        )
89    }
90
91    pub fn is_input_type(&self) -> bool {
92        matches!(
93            self,
94            &TypeDefinition::Scalar(_) | &TypeDefinition::InputObject(_) | &TypeDefinition::Enum(_)
95        )
96    }
97    pub fn is_leaf_type(&self) -> bool {
98        matches!(self, &TypeDefinition::Enum(_) | &TypeDefinition::Scalar(_))
99    }
100
101    pub fn directives(&self) -> &[GqlDirective] {
102        match self {
103            TypeDefinition::Scalar(ty) => &ty.directives,
104            TypeDefinition::Object(ty) => &ty.directives,
105            TypeDefinition::Interface(ty) => &ty.directives,
106            TypeDefinition::Union(ty) => &ty.directives,
107            TypeDefinition::Enum(ty) => &ty.directives,
108            TypeDefinition::InputObject(ty) => &ty.directives,
109        }
110    }
111
112    pub fn field_directives(&self, field_name: &str) -> Vec<GqlDirective> {
113        let mut directives = vec![];
114
115        if let TypeDefinition::Object(obj) = self {
116            for field in &obj.fields {
117                if field.name == field_name {
118                    directives.extend(field.directives.clone());
119                }
120            }
121        }
122        if let TypeDefinition::Interface(interface) = self {
123            for field in &interface.fields {
124                if field.name == field_name {
125                    directives.extend(field.directives.clone());
126                }
127            }
128        }
129        directives
130    }
131
132    pub fn impl_interface_directives(&self, schema: &Schema) -> Vec<GqlDirective> {
133        let mut directives = vec![];
134
135        if let TypeDefinition::Object(obj) = self {
136            for impl_interface in &obj.implements_interfaces {
137                if let Some(interface) = &schema.interfaces.get(impl_interface) {
138                    directives.extend(interface.directives.clone());
139                }
140            }
141        }
142        directives
143    }
144}