In our apollo_compiler::ast level representation, field and directive arguments are represented by Vec<Node<Argument>>, and input object values are represented by Vec<(Name, Node<Value>)>. This is to maintain order and allow the possibility of duplicate names, which are syntactically valid, but not semantically valid.
The lists are normally short so it's not a big deal to have to iterate when you want to look up a particular argument or key. For field and directive arguments, we have an argument_by_name() method that does that for you. However, a malicious input could take a long time if the lists are used inefficiently (for example, an order-independent comparison between input object values that does an O(n^2) nested loop)
The apollo_compiler::{schema,executable} representations could instead use maps for these. A build error would be raised if any duplicates are encountered. We can still store key order by using an IndexMap (this would be good for serialization round-tripping), but ignore key order in == comparisons. It also slightly prevents users from building invalid schemas and operations by not being able to represent duplicate names.
In our
apollo_compiler::ast
level representation, field and directive arguments are represented byVec<Node<Argument>>
, and input object values are represented byVec<(Name, Node<Value>)>
. This is to maintain order and allow the possibility of duplicate names, which are syntactically valid, but not semantically valid.The lists are normally short so it's not a big deal to have to iterate when you want to look up a particular argument or key. For field and directive arguments, we have an
argument_by_name()
method that does that for you. However, a malicious input could take a long time if the lists are used inefficiently (for example, an order-independent comparison between input object values that does an O(n^2) nested loop)The
apollo_compiler::{schema,executable}
representations could instead use maps for these. A build error would be raised if any duplicates are encountered. We can still store key order by using anIndexMap
(this would be good for serialization round-tripping), but ignore key order in==
comparisons. It also slightly prevents users from building invalid schemas and operations by not being able to represent duplicate names.