Skip to main content

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