1
+ // #![deny(missing_docs)]
2
+
1
3
use std:: collections:: HashMap ;
2
4
3
5
use std:: marker:: PhantomData ;
4
6
5
7
use combine:: { Parser , ParseResult , Stream } ;
6
8
use combine:: char:: { tab, char, crlf, string, letter, alpha_num} ;
7
- use combine:: combinator:: { many, none_of, or, optional, value} ;
9
+ use combine:: combinator:: { between , many, none_of, or, optional, value} ;
8
10
9
11
pub type Name = String ;
10
12
pub type SelectionSet = Vec < Selection > ;
11
13
12
- #[ derive( Debug , PartialEq ) ]
14
+ #[ derive( Debug , PartialEq , Clone ) ]
13
15
pub struct Document {
14
16
definitions : Vec < Definition > ,
15
17
}
16
18
17
- #[ derive( Debug , PartialEq ) ]
19
+ #[ derive( Debug , PartialEq , Clone ) ]
18
20
pub enum Definition {
19
21
Operation ( Operation ) ,
20
22
SelectionSet ( SelectionSet ) ,
21
23
Fragment ( Fragment ) ,
22
24
}
23
25
24
- #[ derive( Debug , PartialEq ) ]
26
+ #[ derive( Debug , PartialEq , Clone ) ]
25
27
pub struct Operation {
26
28
op_type : OperationType ,
27
29
name : Option < Name > ,
@@ -44,29 +46,39 @@ impl Operation {
44
46
}
45
47
}
46
48
47
- #[ derive( Debug , PartialEq ) ]
49
+ #[ derive( Debug , PartialEq , Clone ) ]
48
50
pub enum OperationType {
49
51
Query ,
50
52
Mutation ,
51
53
}
52
54
53
- #[ derive( Debug , PartialEq ) ]
55
+ #[ derive( Debug , PartialEq , Clone ) ]
54
56
pub struct VariableDefinition {
55
57
variable : Variable ,
56
58
var_type : Type ,
57
59
default_value : Option < Value > ,
58
60
}
59
61
60
- type Variable = String ;
62
+ impl VariableDefinition {
63
+ fn new ( variable : Variable , var_type : Type , default_value : Option < Value > ) -> VariableDefinition {
64
+ VariableDefinition {
65
+ variable : variable,
66
+ var_type : var_type,
67
+ default_value : default_value,
68
+ }
69
+ }
70
+ }
71
+
72
+ pub type Variable = String ;
61
73
62
- #[ derive( Debug , PartialEq ) ]
74
+ #[ derive( Debug , PartialEq , Clone ) ]
63
75
pub enum Type {
64
76
Named ( Name ) ,
65
77
List ( Box < Type > ) ,
66
78
NonNull ( Box < Type > ) ,
67
79
}
68
80
69
- #[ derive( Debug , PartialEq ) ]
81
+ #[ derive( Debug , PartialEq , Clone ) ]
70
82
pub enum Value {
71
83
Variable ( Variable ) ,
72
84
Int ( i32 ) ,
@@ -79,26 +91,26 @@ pub enum Value {
79
91
Object ( HashMap < String , Value > ) ,
80
92
}
81
93
82
- #[ derive( Debug , PartialEq ) ]
94
+ #[ derive( Debug , PartialEq , Clone ) ]
83
95
pub struct Directive {
84
96
name : Name ,
85
97
arguments : Vec < Argument > ,
86
98
}
87
99
88
- #[ derive( Debug , PartialEq ) ]
100
+ #[ derive( Debug , PartialEq , Clone ) ]
89
101
pub struct Argument {
90
102
name : Name ,
91
103
value : Value ,
92
104
}
93
105
94
- #[ derive( Debug , PartialEq ) ]
106
+ #[ derive( Debug , PartialEq , Clone ) ]
95
107
pub enum Selection {
96
108
Field ( Field ) ,
97
109
FragmentSpread ( Name , Vec < Directive > ) ,
98
110
InlineFragment ( Option < Type > , Vec < Directive > , SelectionSet ) ,
99
111
}
100
112
101
- #[ derive( Debug , PartialEq ) ]
113
+ #[ derive( Debug , PartialEq , Clone ) ]
102
114
pub struct Field {
103
115
alias : Option < Name > ,
104
116
name : Name ,
@@ -124,7 +136,7 @@ impl Field {
124
136
}
125
137
}
126
138
127
- #[ derive( Debug , PartialEq ) ]
139
+ #[ derive( Debug , PartialEq , Clone ) ]
128
140
pub struct Fragment {
129
141
name : Name ,
130
142
type_condition : Type ,
@@ -139,11 +151,14 @@ macro_rules! make_parser {
139
151
140
152
( $name: ident ( $input_var: ident : $input_item_type: ty) -> $output_type: ty { $( $tmpl: tt) * } $( $rest: tt) * ) => {
141
153
142
- pub struct $name<T > {
154
+ #[ derive( Clone ) ]
155
+ #[ allow( missing_docs) ]
156
+ pub struct $name<T : Clone > {
143
157
_phantom: PhantomData <T >,
144
158
}
145
159
146
- impl <T > $name<T > {
160
+ impl <T : Clone > $name<T > {
161
+ #[ allow( missing_docs) ]
147
162
pub fn new( ) -> Self {
148
163
$name {
149
164
_phantom: PhantomData
@@ -166,12 +181,15 @@ macro_rules! make_parser {
166
181
( $name: ident ( $input_var: ident : $input_item_type: ty , $( $field: ident : & $typ: ty) ,* )
167
182
-> $output_type: ty { $( $tmpl: tt) * } $( $rest: tt) * ) => {
168
183
169
- pub struct $name<' a, T > {
184
+ #[ derive( Clone ) ]
185
+ #[ allow( missing_docs) ]
186
+ pub struct $name<' a, T : Clone > {
170
187
_phantom: PhantomData <T >,
171
188
$( $field: & ' a $typ) ,*
172
189
}
173
190
174
- impl <' a, T > $name<' a, T > {
191
+ impl <' a, T : Clone > $name<' a, T > {
192
+ #[ allow( missing_docs) ]
175
193
pub fn new( $( $field: & ' a $typ) ,* ) -> Self {
176
194
$name {
177
195
_phantom: PhantomData ,
@@ -234,15 +252,33 @@ make_parser!(
234
252
) ;
235
253
236
254
make_parser ! (
237
- OperationTypeP ( input: char ) -> OperationType {
255
+ OperationDefinition ( input: char ) -> Operation {
256
+ OperationTypeParserarser :: new( )
257
+ . and( optional( NameParser :: new( ) ) )
258
+ . and( optional( VariableDefinitions :: new( ) ) )
259
+ . map( |( ( op_type, name) , defns) | {
260
+ let variable_definitions = match defns {
261
+ Some ( ds) => ds,
262
+ None => Vec :: new( )
263
+ } ;
264
+
265
+ Operation :: new( op_type, name, variable_definitions, Vec :: new( ) )
266
+ } )
267
+ . parse_stream( input)
268
+ }
269
+ ) ;
270
+
271
+ make_parser ! (
272
+ OperationTypeParserarser ( input: char ) -> OperationType {
238
273
string( "query" ) . map( |_| OperationType :: Query )
239
274
. or( string( "mutation" ) . map( |_| OperationType :: Mutation ) )
275
+ . skip( many:: <Vec <_>, _>( or( WhiteSpace :: new( ) , LineTerminator :: new( & true ) ) ) )
240
276
. parse_stream( input)
241
277
}
242
278
) ;
243
279
244
280
make_parser ! (
245
- NameP ( input: char ) -> Name {
281
+ NameParser ( input: char ) -> Name {
246
282
or( letter( ) , char ( '_' ) )
247
283
. map( |c| {
248
284
let mut result = String :: new( ) ;
@@ -254,35 +290,69 @@ make_parser!(
254
290
f. push_str( & r) ;
255
291
f
256
292
} )
293
+ . skip( many:: <Vec <_>, _>( or( WhiteSpace :: new( ) , LineTerminator :: new( & true ) ) ) )
257
294
. parse_stream( input)
258
295
}
259
296
) ;
260
297
261
298
make_parser ! (
262
- Alias ( input: char ) -> Name {
263
- NameP :: new( )
299
+ VariableDefinitions ( input: char ) -> Vec <VariableDefinition > {
300
+ between( char ( '(' ) , char ( ')' ) , many( VariableDefinitionP :: new( ) ) )
301
+ . parse_stream( input)
302
+ }
303
+ ) ;
304
+
305
+ make_parser ! (
306
+ VariableDefinitionP ( input: char ) -> VariableDefinition {
307
+ VariableParser :: new( )
308
+ . and( TypeParser :: new( ) )
309
+ . map( |( variable, var_type) | {
310
+ VariableDefinition :: new( variable, var_type, None )
311
+ } )
312
+ . parse_stream( input)
313
+ }
314
+ ) ;
315
+
316
+ make_parser ! (
317
+ VariableParser ( input: char ) -> Variable {
318
+ char ( '$' )
319
+ . with( NameParser :: new( ) ) // skip the $
320
+ . parse_stream( input)
321
+ }
322
+ ) ;
323
+
324
+ make_parser ! (
325
+ TypeParser ( input: char ) -> Type {
326
+ let named_type = NameParser :: new( ) . map( Type :: Named ) ;
327
+ let list_type = between( char ( '[' ) , char ( ']' ) , TypeParser :: new( ) ) . map( |t| Type :: List ( Box :: new( t) ) ) ;
328
+
329
+ // i can't clone for some reason -.-
330
+ let non_null_type = char ( '!' )
331
+ . with( or(
332
+ NameParser :: new( ) . map( Type :: Named ) ,
333
+ between( char ( '[' ) , char ( ']' ) , TypeParser :: new( ) ) . map( |t| Type :: List ( Box :: new( t) ) )
334
+ ) )
335
+ . map( |t| Type :: NonNull ( Box :: new( t) ) ) ;
336
+
337
+ non_null_type. or( named_type) . or( list_type)
264
338
. skip( many:: <Vec <_>, _>( or( WhiteSpace :: new( ) , LineTerminator :: new( & true ) ) ) )
265
- . skip( char ( ':' ) )
266
339
. parse_stream( input)
267
340
}
268
341
) ;
269
342
270
343
make_parser ! (
271
- OperationDefinition ( input: char ) -> Operation {
272
- OperationTypeP :: new( )
344
+ Alias ( input: char ) -> Name {
345
+ NameParser :: new( )
273
346
. skip( many:: <Vec <_>, _>( or( WhiteSpace :: new( ) , LineTerminator :: new( & true ) ) ) )
274
- . and( optional( NameP :: new( ) ) )
275
- . map( |( op_type, name) | {
276
- Operation :: new( op_type, name, Vec :: new( ) , Vec :: new( ) )
277
- } )
347
+ . skip( char ( ':' ) )
278
348
. parse_stream( input)
279
349
}
280
350
) ;
281
351
282
352
#[ cfg( test) ]
283
353
mod tests {
284
354
use super :: * ;
285
- use combine:: { Parser , State } ;
355
+ use combine:: { State , Parser } ;
286
356
287
357
macro_rules! assert_successful_parse {
288
358
( $parser: ident, $input: expr, $result: expr) => {
@@ -297,17 +367,19 @@ mod tests {
297
367
298
368
#[ test]
299
369
fn test_parse_operationtype ( ) {
300
- assert_successful_parse ! ( OperationTypeP , "query" , OperationType :: Query ) ;
301
- assert_successful_parse ! ( OperationTypeP , "mutation" , OperationType :: Mutation ) ;
370
+ assert_successful_parse ! ( OperationTypeParserarser , "query" , OperationType :: Query ) ;
371
+ assert_successful_parse ! ( OperationTypeParserarser ,
372
+ "mutation" ,
373
+ OperationType :: Mutation ) ;
302
374
}
303
375
304
376
#[ test]
305
377
fn test_parse_name ( ) {
306
- assert_successful_parse ! ( NameP , "_asd" , String :: from( "_asd" ) ) ;
307
- assert_successful_parse ! ( NameP , "aasd" , String :: from( "aasd" ) ) ;
308
- assert_successful_parse ! ( NameP , "zasd" , String :: from( "zasd" ) ) ;
309
- assert_successful_parse ! ( NameP , "Aasd" , String :: from( "Aasd" ) ) ;
310
- assert_successful_parse ! ( NameP , "Zasd" , String :: from( "Zasd" ) ) ;
378
+ assert_successful_parse ! ( NameParser , "_asd" , String :: from( "_asd" ) ) ;
379
+ assert_successful_parse ! ( NameParser , "aasd" , String :: from( "aasd" ) ) ;
380
+ assert_successful_parse ! ( NameParser , "zasd" , String :: from( "zasd" ) ) ;
381
+ assert_successful_parse ! ( NameParser , "Aasd" , String :: from( "Aasd" ) ) ;
382
+ assert_successful_parse ! ( NameParser , "Zasd" , String :: from( "Zasd" ) ) ;
311
383
}
312
384
313
385
#[ test]
@@ -321,7 +393,10 @@ mod tests {
321
393
fn test_parse_operation ( ) {
322
394
// named operation
323
395
{
324
- let result = Operation :: new ( OperationType :: Mutation , Some ( String :: from ( "test" ) ) , Vec :: new ( ) , Vec :: new ( ) ) ;
396
+ let result = Operation :: new ( OperationType :: Mutation ,
397
+ Some ( String :: from ( "test" ) ) ,
398
+ Vec :: new ( ) ,
399
+ Vec :: new ( ) ) ;
325
400
assert_successful_parse ! ( OperationDefinition , "mutation test" , result) ;
326
401
}
327
402
@@ -331,4 +406,22 @@ mod tests {
331
406
assert_successful_parse ! ( OperationDefinition , "mutation" , result) ;
332
407
}
333
408
}
409
+
410
+ #[ test]
411
+ fn test_parse_type ( ) {
412
+ assert_successful_parse ! ( TypeParser , "User" , Type :: Named ( String :: from( "User" ) ) ) ;
413
+ assert_successful_parse ! ( TypeParser ,
414
+ "[User]" ,
415
+ Type :: List ( Box :: new( Type :: Named ( String :: from( "User" ) ) ) ) ) ;
416
+ }
417
+
418
+ #[ test]
419
+ fn test_parse_nonnull_type ( ) {
420
+ assert_successful_parse ! ( TypeParser ,
421
+ "!User" ,
422
+ Type :: NonNull ( Box :: new( Type :: Named ( String :: from( "User" ) ) ) ) ) ;
423
+ assert_successful_parse ! ( TypeParser ,
424
+ "![User]" ,
425
+ Type :: NonNull ( Box :: new( Type :: List ( Box :: new( Type :: Named ( String :: from( "User" ) ) ) ) ) ) ) ;
426
+ }
334
427
}
0 commit comments