gurkle_parser/schema/
ast.rs

1use std::str::FromStr;
2
3pub use crate::common::{Directive, Name, Type, Value};
4use crate::position::Pos;
5
6pub type NamedType = String;
7
8#[derive(Debug, Clone, Default, PartialEq)]
9pub struct Document {
10    pub definitions: Vec<Definition>,
11}
12
13#[derive(Debug, Clone, PartialEq)]
14pub enum Definition {
15    SchemaDefinition(SchemaDefinition),
16    TypeDefinition(TypeDefinition),
17    TypeExtension(TypeExtension),
18    DirectiveDefinition(DirectiveDefinition),
19}
20
21#[derive(Debug, Clone, Default, PartialEq)]
22pub struct SchemaDefinition {
23    pub position: Pos,
24    pub directives: Vec<Directive>,
25    pub query: Option<NamedType>,
26    pub mutation: Option<NamedType>,
27    pub subscription: Option<NamedType>,
28}
29
30#[derive(Debug, Clone, PartialEq)]
31pub enum TypeDefinition {
32    Scalar(ScalarType),
33    Object(ObjectType),
34    Interface(InterfaceType),
35    Union(UnionType),
36    Enum(EnumType),
37    InputObject(InputObjectType),
38}
39
40#[derive(Debug, Clone, PartialEq)]
41pub enum TypeExtension {
42    Scalar(ScalarTypeExtension),
43    Object(ObjectTypeExtension),
44    Interface(InterfaceTypeExtension),
45    Union(UnionTypeExtension),
46    Enum(EnumTypeExtension),
47    InputObject(InputObjectTypeExtension),
48}
49
50#[derive(Debug, Clone, PartialEq)]
51pub struct ScalarType {
52    pub position: Pos,
53    pub description: Option<String>,
54    pub name: Name,
55    pub directives: Vec<Directive>,
56}
57
58impl ScalarType {
59    pub fn new(name: Name) -> Self {
60        Self {
61            position: Pos::default(),
62            description: None,
63            name,
64            directives: vec![],
65        }
66    }
67}
68
69#[derive(Debug, Clone, PartialEq)]
70pub struct ScalarTypeExtension {
71    pub position: Pos,
72    pub name: Name,
73    pub directives: Vec<Directive>,
74}
75
76impl ScalarTypeExtension {
77    pub fn new(name: Name) -> Self {
78        Self {
79            position: Pos::default(),
80            name,
81            directives: vec![],
82        }
83    }
84}
85
86#[derive(Debug, Clone, PartialEq)]
87pub struct ObjectType {
88    pub position: Pos,
89    pub description: Option<String>,
90    pub name: Name,
91    pub implements_interfaces: Vec<NamedType>,
92    pub directives: Vec<Directive>,
93    pub fields: Vec<Field>,
94}
95
96impl ObjectType {
97    pub fn new(name: Name) -> Self {
98        Self {
99            position: Pos::default(),
100            description: None,
101            name,
102            implements_interfaces: vec![],
103            directives: vec![],
104            fields: vec![],
105        }
106    }
107}
108
109#[derive(Debug, Clone, PartialEq)]
110pub struct ObjectTypeExtension {
111    pub position: Pos,
112    pub name: Name,
113    pub implements_interfaces: Vec<NamedType>,
114    pub directives: Vec<Directive>,
115    pub fields: Vec<Field>,
116}
117
118impl ObjectTypeExtension {
119    pub fn new(name: Name) -> Self {
120        Self {
121            position: Pos::default(),
122            name,
123            implements_interfaces: vec![],
124            directives: vec![],
125            fields: vec![],
126        }
127    }
128}
129
130#[derive(Debug, Clone, PartialEq)]
131pub struct Field {
132    pub position: Pos,
133    pub description: Option<String>,
134    pub name: Name,
135    pub arguments: Vec<InputValue>,
136    pub field_type: Type,
137    pub directives: Vec<Directive>,
138}
139
140#[derive(Debug, Clone, PartialEq)]
141pub struct InputValue {
142    pub position: Pos,
143    pub description: Option<String>,
144    pub name: Name,
145    pub value_type: Type,
146    pub default_value: Option<Value>,
147    pub directives: Vec<Directive>,
148}
149
150#[derive(Debug, Clone, PartialEq)]
151pub struct InterfaceType {
152    pub position: Pos,
153    pub description: Option<String>,
154    pub name: Name,
155    pub directives: Vec<Directive>,
156    pub fields: Vec<Field>,
157}
158
159impl InterfaceType {
160    pub fn new(name: Name) -> Self {
161        Self {
162            position: Pos::default(),
163            description: None,
164            name,
165            directives: vec![],
166            fields: vec![],
167        }
168    }
169}
170
171#[derive(Debug, Clone, PartialEq)]
172pub struct InterfaceTypeExtension {
173    pub position: Pos,
174    pub name: Name,
175    pub directives: Vec<Directive>,
176    pub fields: Vec<Field>,
177}
178
179impl InterfaceTypeExtension {
180    pub fn new(name: Name) -> Self {
181        Self {
182            position: Pos::default(),
183            name,
184            directives: vec![],
185            fields: vec![],
186        }
187    }
188}
189
190#[derive(Debug, Clone, PartialEq)]
191pub struct UnionType {
192    pub position: Pos,
193    pub description: Option<String>,
194    pub name: Name,
195    pub directives: Vec<Directive>,
196    pub types: Vec<NamedType>,
197}
198
199impl UnionType {
200    pub fn new(name: Name) -> Self {
201        Self {
202            position: Pos::default(),
203            description: None,
204            name,
205            directives: vec![],
206            types: vec![],
207        }
208    }
209}
210
211#[derive(Debug, Clone, PartialEq)]
212pub struct UnionTypeExtension {
213    pub position: Pos,
214    pub name: Name,
215    pub directives: Vec<Directive>,
216    pub types: Vec<NamedType>,
217}
218
219impl UnionTypeExtension {
220    pub fn new(name: Name) -> Self {
221        Self {
222            position: Pos::default(),
223            name,
224            directives: vec![],
225            types: vec![],
226        }
227    }
228}
229
230#[derive(Debug, Clone, PartialEq)]
231pub struct EnumType {
232    pub position: Pos,
233    pub description: Option<String>,
234    pub name: Name,
235    pub directives: Vec<Directive>,
236    pub values: Vec<EnumValue>,
237}
238
239impl EnumType {
240    pub fn new(name: Name) -> Self {
241        Self {
242            position: Pos::default(),
243            description: None,
244            name,
245            directives: vec![],
246            values: vec![],
247        }
248    }
249}
250
251#[derive(Debug, Clone, PartialEq)]
252pub struct EnumValue {
253    pub position: Pos,
254    pub description: Option<String>,
255    pub name: Name,
256    pub directives: Vec<Directive>,
257}
258
259impl EnumValue {
260    pub fn new(name: Name) -> Self {
261        Self {
262            position: Pos::default(),
263            description: None,
264            name,
265            directives: vec![],
266        }
267    }
268}
269
270#[derive(Debug, Clone, PartialEq)]
271pub struct EnumTypeExtension {
272    pub position: Pos,
273    pub name: Name,
274    pub directives: Vec<Directive>,
275    pub values: Vec<EnumValue>,
276}
277
278impl EnumTypeExtension {
279    pub fn new(name: Name) -> Self {
280        Self {
281            position: Pos::default(),
282            name,
283            directives: vec![],
284            values: vec![],
285        }
286    }
287}
288
289#[derive(Debug, Clone, PartialEq)]
290pub struct InputObjectType {
291    pub position: Pos,
292    pub description: Option<String>,
293    pub name: Name,
294    pub directives: Vec<Directive>,
295    pub fields: Vec<InputValue>,
296}
297
298impl InputObjectType {
299    pub fn new(name: Name) -> Self {
300        Self {
301            position: Pos::default(),
302            description: None,
303            name,
304            directives: vec![],
305            fields: vec![],
306        }
307    }
308}
309
310#[derive(Debug, Clone, PartialEq)]
311pub struct InputObjectTypeExtension {
312    pub position: Pos,
313    pub name: Name,
314    pub directives: Vec<Directive>,
315    pub fields: Vec<InputValue>,
316}
317
318impl InputObjectTypeExtension {
319    pub fn new(name: Name) -> Self {
320        Self {
321            position: Pos::default(),
322            name,
323            directives: vec![],
324            fields: vec![],
325        }
326    }
327}
328
329#[derive(Debug, Clone, PartialEq, Eq, Hash)]
330pub enum DirectiveLocation {
331    // executable
332    Query,
333    Mutation,
334    Subscription,
335    Field,
336    FragmentDefinition,
337    FragmentSpread,
338    InlineFragment,
339
340    // type_system
341    Schema,
342    Scalar,
343    Object,
344    FieldDefinition,
345    ArgumentDefinition,
346    Interface,
347    Union,
348    Enum,
349    EnumValue,
350    InputObject,
351    InputFieldDefinition,
352}
353
354#[derive(Debug, Clone, PartialEq)]
355pub struct DirectiveDefinition {
356    pub position: Pos,
357    pub description: Option<String>,
358    pub name: Name,
359    pub arguments: Vec<InputValue>,
360    pub repeatable: bool,
361    pub locations: Vec<DirectiveLocation>,
362}
363
364impl DirectiveDefinition {
365    pub fn new(name: Name) -> Self {
366        Self {
367            position: Pos::default(),
368            description: None,
369            name,
370            arguments: vec![],
371            repeatable: false,
372            locations: vec![],
373        }
374    }
375}
376
377impl DirectiveLocation {
378    /// Returns GraphQL syntax compatible name of the directive
379    pub fn as_str(&self) -> &'static str {
380        use self::DirectiveLocation::*;
381        match *self {
382            Query => "QUERY",
383            Mutation => "MUTATION",
384            Subscription => "SUBSCRIPTION",
385            Field => "FIELD",
386            FragmentDefinition => "FRAGMENT_DEFINITION",
387            FragmentSpread => "FRAGMENT_SPREAD",
388            InlineFragment => "INLINE_FRAGMENT",
389            Schema => "SCHEMA",
390            Scalar => "SCALAR",
391            Object => "OBJECT",
392            FieldDefinition => "FIELD_DEFINITION",
393            ArgumentDefinition => "ARGUMENT_DEFINITION",
394            Interface => "INTERFACE",
395            Union => "UNION",
396            Enum => "ENUM",
397            EnumValue => "ENUM_VALUE",
398            InputObject => "INPUT_OBJECT",
399            InputFieldDefinition => "INPUT_FIELD_DEFINITION",
400        }
401    }
402
403    /// Returns `true` if this location is for queries (execution)
404    pub fn is_query(&self) -> bool {
405        use self::DirectiveLocation::*;
406        match *self {
407            Query | Mutation | Subscription | Field | FragmentDefinition | FragmentSpread
408            | InlineFragment => true,
409
410            Schema | Scalar | Object | FieldDefinition | ArgumentDefinition | Interface | Union
411            | Enum | EnumValue | InputObject | InputFieldDefinition => false,
412        }
413    }
414
415    /// Returns `true` if this location is for schema
416    pub fn is_schema(&self) -> bool {
417        !self.is_query()
418    }
419}
420
421#[derive(Debug, thiserror::Error)]
422#[error("invalid directive location")]
423pub struct InvalidDirectiveLocation;
424
425impl FromStr for DirectiveLocation {
426    type Err = InvalidDirectiveLocation;
427    fn from_str(s: &str) -> Result<DirectiveLocation, InvalidDirectiveLocation> {
428        use self::DirectiveLocation::*;
429        let val = match s {
430            "QUERY" => Query,
431            "MUTATION" => Mutation,
432            "SUBSCRIPTION" => Subscription,
433            "FIELD" => Field,
434            "FRAGMENT_DEFINITION" => FragmentDefinition,
435            "FRAGMENT_SPREAD" => FragmentSpread,
436            "INLINE_FRAGMENT" => InlineFragment,
437            "SCHEMA" => Schema,
438            "SCALAR" => Scalar,
439            "OBJECT" => Object,
440            "FIELD_DEFINITION" => FieldDefinition,
441            "ARGUMENT_DEFINITION" => ArgumentDefinition,
442            "INTERFACE" => Interface,
443            "UNION" => Union,
444            "ENUM" => Enum,
445            "ENUM_VALUE" => EnumValue,
446            "INPUT_OBJECT" => InputObject,
447            "INPUT_FIELD_DEFINITION" => InputFieldDefinition,
448            _ => return Err(InvalidDirectiveLocation),
449        };
450
451        Ok(val)
452    }
453}