apollographql / apollo-rs

Spec compliant GraphQL Tools in Rust.
Apache License 2.0
574 stars 45 forks source link

By-name lookup argument lists and input object values in high-level representation #858

Open goto-bus-stop opened 5 months ago

goto-bus-stop commented 5 months ago

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.