graphql_parser/query/
ast.rs

1//! Query Language Abstract Syntax Tree (AST)
2//!
3//! The types and fields here resemble official [graphql grammar] whenever it
4//! makes sense for rust.
5//!
6//! [graphql grammar]: http://facebook.github.io/graphql/October2016/#sec-Appendix-Grammar-Summary
7//!
8use crate::position::Pos;
9pub use crate::common::{Directive, Number, Value, Text, Type};
10
11/// Root of query data
12#[derive(Debug, Clone, PartialEq)]
13pub struct Document<'a, T: Text<'a>> {
14    pub definitions: Vec<Definition<'a, T>>,
15}
16
17impl<'a> Document<'a, String> {
18    pub fn into_static(self) -> Document<'static, String> {
19        // To support both reference and owned values in the AST,
20        // all string data is represented with the ::common::Str<'a, T: Text<'a>> 
21        // wrapper type.
22        // This type must carry the lifetime of the query string,
23        // and is stored in a PhantomData value on the Str type.
24        // When using owned String types, the actual lifetime of
25        // the Ast nodes is 'static, since no references are kept,
26        // but the nodes will still carry the input lifetime.
27        // To continue working with Document<String> in a owned fasion
28        // the lifetime needs to be transmuted to 'static.
29        //
30        // This is safe because no references are present.
31        // Just the PhantomData lifetime reference is transmuted away.
32        unsafe { std::mem::transmute::<_, Document<'static, String>>(self) }
33    }
34}
35
36#[derive(Debug, Clone, PartialEq)]
37pub enum Definition<'a, T: Text<'a>> {
38    Operation(OperationDefinition<'a, T>),
39    Fragment(FragmentDefinition<'a, T>),
40}
41
42#[derive(Debug, Clone, PartialEq)]
43pub struct FragmentDefinition<'a, T: Text<'a>> {
44    pub position: Pos,
45    pub name: T::Value,
46    pub type_condition: TypeCondition<'a, T>,
47    pub directives: Vec<Directive<'a, T>>,
48    pub selection_set: SelectionSet<'a, T>,
49}
50
51#[derive(Debug, Clone, PartialEq)]
52pub enum OperationDefinition<'a, T: Text<'a>> {
53    SelectionSet(SelectionSet<'a, T>),
54    Query(Query<'a, T>),
55    Mutation(Mutation<'a, T>),
56    Subscription(Subscription<'a, T>),
57}
58
59#[derive(Debug, Clone, PartialEq)]
60pub struct Query<'a, T: Text<'a>> {
61    pub position: Pos,
62    pub name: Option<T::Value>,
63    pub variable_definitions: Vec<VariableDefinition<'a, T>>,
64    pub directives: Vec<Directive<'a, T>>,
65    pub selection_set: SelectionSet<'a, T>,
66}
67
68#[derive(Debug, Clone, PartialEq)]
69pub struct Mutation<'a, T: Text<'a>> {
70    pub position: Pos,
71    pub name: Option<T::Value>,
72    pub variable_definitions: Vec<VariableDefinition<'a, T>>,
73    pub directives: Vec<Directive<'a, T>>,
74    pub selection_set: SelectionSet<'a, T>,
75}
76
77#[derive(Debug, Clone, PartialEq)]
78pub struct Subscription<'a, T: Text<'a>> {
79    pub position: Pos,
80    pub name: Option<T::Value>,
81    pub variable_definitions: Vec<VariableDefinition<'a, T>>,
82    pub directives: Vec<Directive<'a, T>>,
83    pub selection_set: SelectionSet<'a, T>,
84}
85
86#[derive(Debug, Clone, PartialEq)]
87pub struct SelectionSet<'a, T: Text<'a>> {
88    pub span: (Pos, Pos),
89    pub items: Vec<Selection<'a, T>>,
90}
91
92#[derive(Debug, Clone, PartialEq)]
93pub struct VariableDefinition<'a, T: Text<'a>> {
94    pub position: Pos,
95    pub name: T::Value,
96    pub var_type: Type<'a, T>,
97    pub default_value: Option<Value<'a, T>>,
98}
99
100#[derive(Debug, Clone, PartialEq)]
101pub enum Selection<'a, T: Text<'a>> {
102    Field(Field<'a, T>),
103    FragmentSpread(FragmentSpread<'a, T>),
104    InlineFragment(InlineFragment<'a, T>),
105}
106
107#[derive(Debug, Clone, PartialEq)]
108pub struct Field<'a, T: Text<'a>> {
109    pub position: Pos,
110    pub alias: Option<T::Value>,
111    pub name: T::Value,
112    pub arguments: Vec<(T::Value, Value<'a, T>)>,
113    pub directives: Vec<Directive<'a, T>>,
114    pub selection_set: SelectionSet<'a, T>,
115}
116
117#[derive(Debug, Clone, PartialEq)]
118pub struct FragmentSpread<'a, T: Text<'a>> {
119    pub position: Pos,
120    pub fragment_name: T::Value,
121    pub directives: Vec<Directive<'a, T>>,
122}
123
124#[derive(Debug, Clone, PartialEq)]
125pub enum TypeCondition<'a, T: Text<'a>> {
126    On(T::Value),
127}
128
129#[derive(Debug, Clone, PartialEq)]
130pub struct InlineFragment<'a, T: Text<'a>> {
131    pub position: Pos,
132    pub type_condition: Option<TypeCondition<'a, T>>,
133    pub directives: Vec<Directive<'a, T>>,
134    pub selection_set: SelectionSet<'a, T>,
135}