@@ -3,7 +3,7 @@ use std::{collections::HashSet, ops::Deref};
3
3
use graph:: {
4
4
components:: store:: EntityType ,
5
5
data:: graphql:: { DocumentExt , ObjectOrInterface } ,
6
- prelude:: { anyhow, q, r, s, QueryExecutionError , Schema , ValueMap } ,
6
+ prelude:: { anyhow, q, r, s, ApiSchema , QueryExecutionError , ValueMap } ,
7
7
} ;
8
8
use graphql_parser:: Pos ;
9
9
@@ -23,13 +23,16 @@ use crate::schema::ast::ObjectType;
23
23
pub struct SelectionSet {
24
24
// Map object types to the list of fields that should be selected for
25
25
// them
26
- items : Vec < ( String , Vec < Field > ) > ,
26
+ items : Vec < ( ObjectType , Vec < Field > ) > ,
27
27
}
28
28
29
29
impl SelectionSet {
30
30
/// Create a new `SelectionSet` that can handle the given types
31
- pub fn new ( types : Vec < String > ) -> Self {
32
- let items = types. into_iter ( ) . map ( |name| ( name, Vec :: new ( ) ) ) . collect ( ) ;
31
+ pub fn new ( types : Vec < ObjectType > ) -> Self {
32
+ let items = types
33
+ . into_iter ( )
34
+ . map ( |obj_type| ( obj_type, Vec :: new ( ) ) )
35
+ . collect ( ) ;
33
36
SelectionSet { items }
34
37
}
35
38
@@ -76,29 +79,28 @@ impl SelectionSet {
76
79
}
77
80
78
81
/// Iterate over all types and the fields for those types
79
- pub fn fields ( & self ) -> impl Iterator < Item = ( & str , impl Iterator < Item = & Field > ) > {
82
+ pub fn fields ( & self ) -> impl Iterator < Item = ( & ObjectType , impl Iterator < Item = & Field > ) > {
80
83
self . items
81
84
. iter ( )
82
- . map ( |( name , fields) | ( name . as_str ( ) , fields. iter ( ) ) )
85
+ . map ( |( obj_type , fields) | ( obj_type , fields. iter ( ) ) )
83
86
}
84
87
85
88
/// Iterate over all types and the fields that are not leaf fields, i.e.
86
89
/// whose selection sets are not empty
87
- pub fn interior_fields ( & self ) -> impl Iterator < Item = ( & str , impl Iterator < Item = & Field > ) > {
88
- self . items . iter ( ) . map ( |( name, fields) | {
89
- (
90
- name. as_str ( ) ,
91
- fields. iter ( ) . filter ( |field| !field. is_leaf ( ) ) ,
92
- )
93
- } )
90
+ pub fn interior_fields (
91
+ & self ,
92
+ ) -> impl Iterator < Item = ( & ObjectType , impl Iterator < Item = & Field > ) > {
93
+ self . items
94
+ . iter ( )
95
+ . map ( |( obj_type, fields) | ( obj_type, fields. iter ( ) . filter ( |field| !field. is_leaf ( ) ) ) )
94
96
}
95
97
96
98
/// Iterate over all fields for the given object type
97
- pub fn fields_for ( & self , obj_type : & s :: ObjectType ) -> impl Iterator < Item = & Field > {
99
+ pub fn fields_for ( & self , obj_type : & ObjectType ) -> impl Iterator < Item = & Field > {
98
100
let item = self
99
101
. items
100
102
. iter ( )
101
- . find ( |( name , _) | name == & obj_type. name )
103
+ . find ( |( our_type , _) | our_type == obj_type)
102
104
. expect ( "there is an entry for the type" ) ;
103
105
item. 1 . iter ( )
104
106
}
@@ -254,14 +256,14 @@ impl ValueMap for Field {
254
256
/// object types that implement them, and possibly narrowing further when
255
257
/// expanding fragments with type conitions
256
258
#[ derive( Debug , Clone , PartialEq ) ]
257
- pub enum ObjectTypeSet {
259
+ pub ( crate ) enum ObjectTypeSet {
258
260
Any ,
259
- Only ( HashSet < String > ) ,
261
+ Only ( HashSet < ObjectType > ) ,
260
262
}
261
263
262
264
impl ObjectTypeSet {
263
265
pub fn convert (
264
- schema : & Schema ,
266
+ schema : & ApiSchema ,
265
267
type_cond : Option < & q:: TypeCondition > ,
266
268
) -> Result < ObjectTypeSet , QueryExecutionError > {
267
269
match type_cond {
@@ -270,64 +272,60 @@ impl ObjectTypeSet {
270
272
}
271
273
}
272
274
273
- pub fn from_name ( schema : & Schema , name : & str ) -> Result < ObjectTypeSet , QueryExecutionError > {
274
- let set = resolve_object_types ( schema, name) ?
275
- . into_iter ( )
276
- . map ( |ty| ty. name ( ) . to_string ( ) )
277
- . collect ( ) ;
275
+ pub fn from_name ( schema : & ApiSchema , name : & str ) -> Result < ObjectTypeSet , QueryExecutionError > {
276
+ let set = resolve_object_types ( schema, name) ?;
278
277
Ok ( ObjectTypeSet :: Only ( set) )
279
278
}
280
279
281
- fn matches_name ( & self , name : & str ) -> bool {
280
+ fn contains ( & self , obj_type : & ObjectType ) -> bool {
282
281
match self {
283
282
ObjectTypeSet :: Any => true ,
284
- ObjectTypeSet :: Only ( set) => set. contains ( name ) ,
283
+ ObjectTypeSet :: Only ( set) => set. contains ( obj_type ) ,
285
284
}
286
285
}
287
286
288
287
pub fn intersect ( self , other : & ObjectTypeSet ) -> ObjectTypeSet {
289
288
match self {
290
289
ObjectTypeSet :: Any => other. clone ( ) ,
291
- ObjectTypeSet :: Only ( set) => ObjectTypeSet :: Only (
292
- set. into_iter ( )
293
- . filter ( |ty| other. matches_name ( ty) )
294
- . collect ( ) ,
295
- ) ,
290
+ ObjectTypeSet :: Only ( set) => {
291
+ ObjectTypeSet :: Only ( set. into_iter ( ) . filter ( |ty| other. contains ( ty) ) . collect ( ) )
292
+ }
296
293
}
297
294
}
298
295
299
296
/// Return a list of the object type names that are in this type set and
300
297
/// are also implementations of `current_type`
301
298
pub fn type_names (
302
299
& self ,
303
- schema : & Schema ,
300
+ schema : & ApiSchema ,
304
301
current_type : ObjectOrInterface < ' _ > ,
305
- ) -> Result < Vec < String > , QueryExecutionError > {
302
+ ) -> Result < Vec < ObjectType > , QueryExecutionError > {
306
303
Ok ( resolve_object_types ( schema, current_type. name ( ) ) ?
307
304
. into_iter ( )
308
- . map ( |obj| obj. name ( ) . to_string ( ) )
309
- . filter ( |name| match self {
305
+ . filter ( |obj_type| match self {
310
306
ObjectTypeSet :: Any => true ,
311
- ObjectTypeSet :: Only ( set) => set. contains ( name . as_str ( ) ) ,
307
+ ObjectTypeSet :: Only ( set) => set. contains ( obj_type ) ,
312
308
} )
313
- . collect :: < Vec < String > > ( ) )
309
+ . collect ( ) )
314
310
}
315
311
}
316
312
317
313
/// Look up the type `name` from the schema and resolve interfaces
318
314
/// and unions until we are left with a set of concrete object types
319
- pub ( crate ) fn resolve_object_types < ' a > (
320
- schema : & ' a Schema ,
315
+ pub ( crate ) fn resolve_object_types (
316
+ schema : & ApiSchema ,
321
317
name : & str ,
322
- ) -> Result < HashSet < ObjectType < ' a > > , QueryExecutionError > {
318
+ ) -> Result < HashSet < ObjectType > , QueryExecutionError > {
323
319
let mut set = HashSet :: new ( ) ;
324
320
match schema
321
+ . schema
325
322
. document
326
323
. get_named_type ( name)
327
324
. ok_or_else ( || QueryExecutionError :: AbstractTypeError ( name. to_string ( ) ) ) ?
328
325
{
329
326
s:: TypeDefinition :: Interface ( intf) => {
330
327
for obj_ty in & schema. types_for_interface ( ) [ & EntityType :: new ( intf. name . to_string ( ) ) ] {
328
+ let obj_ty = schema. object_type ( obj_ty) ;
331
329
set. insert ( obj_ty. into ( ) ) ;
332
330
}
333
331
}
@@ -337,6 +335,7 @@ pub(crate) fn resolve_object_types<'a>(
337
335
}
338
336
}
339
337
s:: TypeDefinition :: Object ( ty) => {
338
+ let ty = schema. object_type ( ty) ;
340
339
set. insert ( ty. into ( ) ) ;
341
340
}
342
341
s:: TypeDefinition :: Scalar ( _)
0 commit comments