1
- use crate :: graphql:: * ;
1
+ use crate :: graphql:: { EnumSource , __InputValue , __Type , ___Type } ;
2
2
use crate :: gson;
3
3
use graphql_parser:: query:: * ;
4
- use graphql_parser:: Pos ;
5
4
use std:: collections:: HashMap ;
6
5
7
6
pub fn alias_or_name < ' a , T > ( query_field : & graphql_parser:: query:: Field < ' a , T > ) -> String
@@ -15,221 +14,34 @@ where
15
14
. unwrap_or_else ( || query_field. name . as_ref ( ) . to_string ( ) )
16
15
}
17
16
18
- pub fn merge_fields < ' a , T , I > (
19
- target_fields : & mut Vec < Field < ' a , T > > ,
20
- next_fields : I ,
21
- type_name : & str ,
22
- field_map : & HashMap < String , __Field > ,
23
- ) -> Result < ( ) , String >
24
- where
25
- T : Text < ' a > + Eq + AsRef < str > + std:: fmt:: Debug + Clone ,
26
- I : IntoIterator < Item = Field < ' a , T > > ,
27
- {
28
- for field in next_fields {
29
- merge_field ( target_fields, field, type_name, field_map) ?
30
- }
31
- Ok ( ( ) )
32
- }
33
-
34
- pub fn merge_field < ' a , T > (
35
- target_fields : & mut Vec < Field < ' a , T > > ,
36
- mut field : Field < ' a , T > ,
37
- type_name : & str ,
38
- field_map : & HashMap < String , __Field > ,
39
- ) -> Result < ( ) , String >
40
- where
41
- T : Text < ' a > + Eq + AsRef < str > + std:: fmt:: Debug + Clone ,
42
- {
43
- let Some ( ( matching_idx, matching_field) ) = target_fields
44
- . iter ( )
45
- . enumerate ( )
46
- . find ( |( _, target) | alias_or_name ( target) == alias_or_name ( & field) )
47
- else {
48
- target_fields. push ( field) ;
49
- return Ok ( ( ) ) ;
50
- } ;
51
-
52
- can_fields_merge ( matching_field, & field, type_name, field_map) ?;
53
-
54
- field. position = field. position . min ( matching_field. position ) ;
55
-
56
- field. selection_set . span =
57
- min_encapsulating_span ( field. selection_set . span , matching_field. selection_set . span ) ;
58
-
59
- // Subfields will be normalized and properly merged on a later pass.
60
- field
61
- . selection_set
62
- . items
63
- . extend ( matching_field. selection_set . items . clone ( ) ) ;
64
-
65
- target_fields[ matching_idx] = field;
66
-
67
- Ok ( ( ) )
68
- }
69
-
70
- pub fn can_fields_merge < ' a , T > (
71
- field_a : & Field < ' a , T > ,
72
- field_b : & Field < ' a , T > ,
73
- type_name : & str ,
74
- field_map : & HashMap < String , __Field > ,
75
- ) -> Result < ( ) , String >
76
- where
77
- T : Text < ' a > + Eq + AsRef < str > + std:: fmt:: Debug + Clone ,
78
- {
79
- let Some ( _field_a) = field_map. get ( field_a. name . as_ref ( ) ) else {
80
- return Err ( format ! (
81
- "Unknown field '{}' on type '{}'" ,
82
- field_a. name. as_ref( ) ,
83
- type_name
84
- ) ) ;
85
- } ;
86
- let Some ( _field_b) = field_map. get ( field_b. name . as_ref ( ) ) else {
87
- return Err ( format ! (
88
- "Unknown field '{}' on type '{}'" ,
89
- field_b. name. as_ref( ) ,
90
- type_name
91
- ) ) ;
92
- } ;
93
-
94
- has_same_type_shape (
95
- & alias_or_name ( field_a) ,
96
- type_name,
97
- & _field_a. type_ ,
98
- & _field_b. type_ ,
99
- ) ?;
100
-
101
- if field_a. name != field_b. name {
102
- return Err ( format ! (
103
- "Fields '{}' on type '{}' conflict because '{}' and '{}' are different fields" ,
104
- alias_or_name( field_a) ,
105
- type_name,
106
- field_a. name. as_ref( ) ,
107
- field_b. name. as_ref( ) ,
108
- ) ) ;
109
- }
110
-
111
- for ( arg_a_name, arg_a_value) in field_a. arguments . iter ( ) {
112
- let arg_b_value = field_b. arguments . iter ( ) . find_map ( |( name, value) | {
113
- if name == arg_a_name {
114
- Some ( value)
115
- } else {
116
- None
117
- }
118
- } ) ;
119
- let args_match = match arg_b_value {
120
- None => false ,
121
- Some ( arg_b_value) => arg_b_value == arg_a_value,
122
- } ;
123
- if !args_match {
124
- return Err ( format ! (
125
- "Fields '{}' on type '{}' conflict because they have differing arguments" ,
126
- alias_or_name( field_a) ,
127
- type_name,
128
- ) ) ;
129
- }
130
- }
131
-
132
- Ok ( ( ) )
133
- }
134
-
135
- pub fn has_same_type_shape (
136
- field_name : & str ,
137
- type_name : & str ,
138
- type_a : & __Type ,
139
- type_b : & __Type ,
140
- ) -> Result < ( ) , String > {
141
- let mut type_a = type_a;
142
- let mut type_b = type_b;
143
-
144
- if matches ! ( type_a, __Type:: NonNull ( _) ) || matches ! ( type_b, __Type:: NonNull ( _) ) {
145
- if let ( __Type:: NonNull ( nullable_type_a) , __Type:: NonNull ( nullable_type_b) ) =
146
- ( type_a, type_b)
147
- {
148
- type_a = nullable_type_a. type_ . as_ref ( ) ;
149
- type_b = nullable_type_b. type_ . as_ref ( ) ;
150
- } else {
151
- return Err ( format ! (
152
- "Fields '{}' on type '{}' conflict because only one is non nullable" ,
153
- field_name, type_name,
154
- ) ) ;
155
- }
156
- }
157
-
158
- if matches ! ( type_a, __Type:: List ( _) ) || matches ! ( type_b, __Type:: List ( _) ) {
159
- if let ( __Type:: List ( list_type_a) , __Type:: List ( list_type_b) ) = ( type_a, type_b) {
160
- type_a = list_type_a. type_ . as_ref ( ) ;
161
- type_b = list_type_b. type_ . as_ref ( ) ;
162
- } else {
163
- return Err ( format ! (
164
- "Fields '{}' on type '{}' conflict because only one is a list type" ,
165
- field_name, type_name,
166
- ) ) ;
167
- }
168
-
169
- return has_same_type_shape ( field_name, type_name, type_a, type_b) ;
170
- }
171
-
172
- if matches ! ( type_a, __Type:: Enum ( _) )
173
- || matches ! ( type_b, __Type:: Enum ( _) )
174
- || matches ! ( type_a, __Type:: Scalar ( _) )
175
- || matches ! ( type_b, __Type:: Scalar ( _) )
176
- {
177
- return if type_a == type_b {
178
- Ok ( ( ) )
179
- } else {
180
- Err ( format ! (
181
- "Fields '{}' on type '{}' conflict due to mismatched types" ,
182
- field_name, type_name,
183
- ) )
184
- } ;
185
- }
186
-
187
- // TODO handle composite types?
188
-
189
- // Subfield type shapes will be checked on a later pass.
190
- Ok ( ( ) )
191
- }
192
-
193
- pub fn min_encapsulating_span ( a : ( Pos , Pos ) , b : ( Pos , Pos ) ) -> ( Pos , Pos ) {
194
- ( a. 0 . min ( b. 0 ) , a. 1 . max ( b. 1 ) )
195
- }
196
-
197
- pub fn normalize_selection_set < ' a , T > (
198
- selection_set : & SelectionSet < ' a , T > ,
199
- fragment_definitions : & Vec < FragmentDefinition < ' a , T > > ,
17
+ pub fn normalize_selection_set < ' a , ' b , T > (
18
+ selection_set : & ' b SelectionSet < ' a , T > ,
19
+ fragment_definitions : & ' b Vec < FragmentDefinition < ' a , T > > ,
200
20
type_name : & String , // for inline fragments
201
21
variables : & serde_json:: Value , // for directives
202
- field_type : & __Type ,
203
- ) -> Result < Vec < Field < ' a , T > > , String >
22
+ ) -> Result < Vec < & ' b Field < ' a , T > > , String >
204
23
where
205
- T : Text < ' a > + Eq + AsRef < str > + std :: fmt :: Debug + Clone ,
24
+ T : Text < ' a > + Eq + AsRef < str > ,
206
25
{
207
- let mut normalized_fields: Vec < Field < ' a , T > > = vec ! [ ] ;
208
-
209
- let field_map = field_map ( & field_type. unmodified_type ( ) ) ;
26
+ let mut selections: Vec < & ' b Field < ' a , T > > = vec ! [ ] ;
210
27
211
28
for selection in & selection_set. items {
212
- match normalize_selection (
213
- selection,
214
- fragment_definitions,
215
- type_name,
216
- variables,
217
- field_type,
218
- ) {
219
- Ok ( fields) => merge_fields ( & mut normalized_fields, fields, type_name, & field_map) ?,
29
+ let sel = selection;
30
+ match normalize_selection ( sel, fragment_definitions, type_name, variables) {
31
+ Ok ( sels) => selections. extend ( sels) ,
220
32
Err ( err) => return Err ( err) ,
221
33
}
222
34
}
223
- Ok ( normalized_fields )
35
+ Ok ( selections )
224
36
}
225
37
226
38
/// Combines @skip and @include
227
- pub fn selection_is_skipped < ' a , T > (
228
- query_selection : & Selection < ' a , T > ,
39
+ pub fn selection_is_skipped < ' a , ' b , T > (
40
+ query_selection : & ' b Selection < ' a , T > ,
229
41
variables : & serde_json:: Value ,
230
42
) -> Result < bool , String >
231
43
where
232
- T : Text < ' a > + Eq + AsRef < str > + std :: fmt :: Debug ,
44
+ T : Text < ' a > + Eq + AsRef < str > ,
233
45
{
234
46
let directives = match query_selection {
235
47
Selection :: Field ( x) => & x. directives ,
@@ -318,27 +130,24 @@ where
318
130
}
319
131
320
132
/// Normalizes literal selections, fragment spreads, and inline fragments
321
- pub fn normalize_selection < ' a , T > (
322
- query_selection : & Selection < ' a , T > ,
323
- fragment_definitions : & Vec < FragmentDefinition < ' a , T > > ,
133
+ pub fn normalize_selection < ' a , ' b , T > (
134
+ query_selection : & ' b Selection < ' a , T > ,
135
+ fragment_definitions : & ' b Vec < FragmentDefinition < ' a , T > > ,
324
136
type_name : & String , // for inline fragments
325
137
variables : & serde_json:: Value , // for directives
326
- field_type : & __Type , // for field merging shape check
327
- ) -> Result < Vec < Field < ' a , T > > , String >
138
+ ) -> Result < Vec < & ' b Field < ' a , T > > , String >
328
139
where
329
- T : Text < ' a > + Eq + AsRef < str > + std :: fmt :: Debug + Clone ,
140
+ T : Text < ' a > + Eq + AsRef < str > ,
330
141
{
331
- let mut normalized_fields : Vec < Field < ' a , T > > = vec ! [ ] ;
142
+ let mut selections : Vec < & Field < ' a , T > > = vec ! [ ] ;
332
143
333
144
if selection_is_skipped ( query_selection, variables) ? {
334
- return Ok ( normalized_fields ) ;
145
+ return Ok ( selections ) ;
335
146
}
336
147
337
- let field_map = field_map ( & field_type. unmodified_type ( ) ) ;
338
-
339
148
match query_selection {
340
149
Selection :: Field ( field) => {
341
- merge_field ( & mut normalized_fields , field . clone ( ) , type_name , & field_map ) ? ;
150
+ selections . push ( field ) ;
342
151
}
343
152
Selection :: FragmentSpread ( fragment_spread) => {
344
153
let frag_name = & fragment_spread. fragment_name ;
@@ -364,15 +173,14 @@ where
364
173
} ;
365
174
366
175
// TODO handle directives?
367
- let frag_fields = normalize_selection_set (
176
+ let frag_selections = normalize_selection_set (
368
177
& frag_def. selection_set ,
369
178
fragment_definitions,
370
179
type_name,
371
180
variables,
372
- field_type,
373
181
) ;
374
- match frag_fields {
375
- Ok ( fields ) => merge_fields ( & mut normalized_fields , fields , type_name , & field_map ) ? ,
182
+ match frag_selections {
183
+ Ok ( sels ) => selections . extend ( sels . iter ( ) ) ,
376
184
Err ( err) => return Err ( err) ,
377
185
} ;
378
186
}
@@ -385,19 +193,18 @@ where
385
193
} ;
386
194
387
195
if inline_fragment_applies {
388
- let infrag_fields = normalize_selection_set (
196
+ let infrag_selections = normalize_selection_set (
389
197
& inline_fragment. selection_set ,
390
198
fragment_definitions,
391
199
type_name,
392
200
variables,
393
- field_type,
394
201
) ?;
395
- merge_fields ( & mut normalized_fields , infrag_fields , type_name , & field_map ) ? ;
202
+ selections . extend ( infrag_selections . iter ( ) ) ;
396
203
}
397
204
}
398
205
}
399
206
400
- Ok ( normalized_fields )
207
+ Ok ( selections )
401
208
}
402
209
403
210
pub fn to_gson < ' a , T > (
@@ -406,7 +213,7 @@ pub fn to_gson<'a, T>(
406
213
variable_definitions : & Vec < VariableDefinition < ' a , T > > ,
407
214
) -> Result < gson:: Value , String >
408
215
where
409
- T : Text < ' a > + AsRef < str > + std :: fmt :: Debug ,
216
+ T : Text < ' a > + AsRef < str > ,
410
217
{
411
218
let result = match graphql_value {
412
219
Value :: Null => gson:: Value :: Null ,
@@ -466,6 +273,7 @@ where
466
273
}
467
274
468
275
pub fn validate_arg_from_type ( type_ : & __Type , value : & gson:: Value ) -> Result < gson:: Value , String > {
276
+ use crate :: graphql:: Scalar ;
469
277
use crate :: gson:: Number as GsonNumber ;
470
278
use crate :: gson:: Value as GsonValue ;
471
279
@@ -676,6 +484,7 @@ pub fn validate_arg_from_input_object(
676
484
input_type : & __Type ,
677
485
value : & gson:: Value ,
678
486
) -> Result < gson:: Value , String > {
487
+ use crate :: graphql:: __TypeKind;
679
488
use crate :: gson:: Value as GsonValue ;
680
489
681
490
let input_type_name = input_type. name ( ) . unwrap_or_default ( ) ;
0 commit comments