Performance improvements (#202)
Performance improvements * Replace the IndexMap in the serialized object with a plain `Vec<(String, Value)>` because linear search is faster for few elements * Some general tweaks to skip some allocations
This commit is contained in:
parent
56f71e934b
commit
90b89f00ee
22 changed files with 614 additions and 353 deletions
|
@ -1,9 +1,7 @@
|
|||
use indexmap::IndexMap;
|
||||
|
||||
use executor::Variables;
|
||||
use schema::model::RootNode;
|
||||
use types::scalars::EmptyMutation;
|
||||
use value::Value;
|
||||
use value::{Value, Object};
|
||||
|
||||
struct TestType;
|
||||
|
||||
|
@ -19,7 +17,7 @@ graphql_object!(TestType: () |&self| {
|
|||
|
||||
fn run_variable_query<F>(query: &str, vars: Variables, f: F)
|
||||
where
|
||||
F: Fn(&IndexMap<String, Value>) -> (),
|
||||
F: Fn(&Object) -> (),
|
||||
{
|
||||
let schema = RootNode::new(TestType, EmptyMutation::<()>::new());
|
||||
|
||||
|
@ -36,7 +34,7 @@ where
|
|||
|
||||
fn run_query<F>(query: &str, f: F)
|
||||
where
|
||||
F: Fn(&IndexMap<String, Value>) -> (),
|
||||
F: Fn(&Object) -> (),
|
||||
{
|
||||
run_variable_query(query, Variables::new(), f);
|
||||
}
|
||||
|
@ -44,32 +42,32 @@ where
|
|||
#[test]
|
||||
fn scalar_include_true() {
|
||||
run_query("{ a, b @include(if: true) }", |result| {
|
||||
assert_eq!(result.get("a"), Some(&Value::string("a")));
|
||||
assert_eq!(result.get("b"), Some(&Value::string("b")));
|
||||
assert_eq!(result.get_field_value("a"), Some(&Value::string("a")));
|
||||
assert_eq!(result.get_field_value("b"), Some(&Value::string("b")));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn scalar_include_false() {
|
||||
run_query("{ a, b @include(if: false) }", |result| {
|
||||
assert_eq!(result.get("a"), Some(&Value::string("a")));
|
||||
assert_eq!(result.get("b"), None);
|
||||
assert_eq!(result.get_field_value("a"), Some(&Value::string("a")));
|
||||
assert_eq!(result.get_field_value("b"), None);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn scalar_skip_false() {
|
||||
run_query("{ a, b @skip(if: false) }", |result| {
|
||||
assert_eq!(result.get("a"), Some(&Value::string("a")));
|
||||
assert_eq!(result.get("b"), Some(&Value::string("b")));
|
||||
assert_eq!(result.get_field_value("a"), Some(&Value::string("a")));
|
||||
assert_eq!(result.get_field_value("b"), Some(&Value::string("b")));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn scalar_skip_true() {
|
||||
run_query("{ a, b @skip(if: true) }", |result| {
|
||||
assert_eq!(result.get("a"), Some(&Value::string("a")));
|
||||
assert_eq!(result.get("b"), None);
|
||||
assert_eq!(result.get_field_value("a"), Some(&Value::string("a")));
|
||||
assert_eq!(result.get_field_value("b"), None);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -78,8 +76,8 @@ fn fragment_spread_include_true() {
|
|||
run_query(
|
||||
"{ a, ...Frag @include(if: true) } fragment Frag on TestType { b }",
|
||||
|result| {
|
||||
assert_eq!(result.get("a"), Some(&Value::string("a")));
|
||||
assert_eq!(result.get("b"), Some(&Value::string("b")));
|
||||
assert_eq!(result.get_field_value("a"), Some(&Value::string("a")));
|
||||
assert_eq!(result.get_field_value("b"), Some(&Value::string("b")));
|
||||
},
|
||||
);
|
||||
}
|
||||
|
@ -89,8 +87,8 @@ fn fragment_spread_include_false() {
|
|||
run_query(
|
||||
"{ a, ...Frag @include(if: false) } fragment Frag on TestType { b }",
|
||||
|result| {
|
||||
assert_eq!(result.get("a"), Some(&Value::string("a")));
|
||||
assert_eq!(result.get("b"), None);
|
||||
assert_eq!(result.get_field_value("a"), Some(&Value::string("a")));
|
||||
assert_eq!(result.get_field_value("b"), None);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
@ -100,8 +98,8 @@ fn fragment_spread_skip_false() {
|
|||
run_query(
|
||||
"{ a, ...Frag @skip(if: false) } fragment Frag on TestType { b }",
|
||||
|result| {
|
||||
assert_eq!(result.get("a"), Some(&Value::string("a")));
|
||||
assert_eq!(result.get("b"), Some(&Value::string("b")));
|
||||
assert_eq!(result.get_field_value("a"), Some(&Value::string("a")));
|
||||
assert_eq!(result.get_field_value("b"), Some(&Value::string("b")));
|
||||
},
|
||||
);
|
||||
}
|
||||
|
@ -111,8 +109,8 @@ fn fragment_spread_skip_true() {
|
|||
run_query(
|
||||
"{ a, ...Frag @skip(if: true) } fragment Frag on TestType { b }",
|
||||
|result| {
|
||||
assert_eq!(result.get("a"), Some(&Value::string("a")));
|
||||
assert_eq!(result.get("b"), None);
|
||||
assert_eq!(result.get_field_value("a"), Some(&Value::string("a")));
|
||||
assert_eq!(result.get_field_value("b"), None);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
@ -122,8 +120,8 @@ fn inline_fragment_include_true() {
|
|||
run_query(
|
||||
"{ a, ... on TestType @include(if: true) { b } }",
|
||||
|result| {
|
||||
assert_eq!(result.get("a"), Some(&Value::string("a")));
|
||||
assert_eq!(result.get("b"), Some(&Value::string("b")));
|
||||
assert_eq!(result.get_field_value("a"), Some(&Value::string("a")));
|
||||
assert_eq!(result.get_field_value("b"), Some(&Value::string("b")));
|
||||
},
|
||||
);
|
||||
}
|
||||
|
@ -133,8 +131,8 @@ fn inline_fragment_include_false() {
|
|||
run_query(
|
||||
"{ a, ... on TestType @include(if: false) { b } }",
|
||||
|result| {
|
||||
assert_eq!(result.get("a"), Some(&Value::string("a")));
|
||||
assert_eq!(result.get("b"), None);
|
||||
assert_eq!(result.get_field_value("a"), Some(&Value::string("a")));
|
||||
assert_eq!(result.get_field_value("b"), None);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
@ -142,79 +140,79 @@ fn inline_fragment_include_false() {
|
|||
#[test]
|
||||
fn inline_fragment_skip_false() {
|
||||
run_query("{ a, ... on TestType @skip(if: false) { b } }", |result| {
|
||||
assert_eq!(result.get("a"), Some(&Value::string("a")));
|
||||
assert_eq!(result.get("b"), Some(&Value::string("b")));
|
||||
assert_eq!(result.get_field_value("a"), Some(&Value::string("a")));
|
||||
assert_eq!(result.get_field_value("b"), Some(&Value::string("b")));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn inline_fragment_skip_true() {
|
||||
run_query("{ a, ... on TestType @skip(if: true) { b } }", |result| {
|
||||
assert_eq!(result.get("a"), Some(&Value::string("a")));
|
||||
assert_eq!(result.get("b"), None);
|
||||
assert_eq!(result.get_field_value("a"), Some(&Value::string("a")));
|
||||
assert_eq!(result.get_field_value("b"), None);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn anonymous_inline_fragment_include_true() {
|
||||
run_query("{ a, ... @include(if: true) { b } }", |result| {
|
||||
assert_eq!(result.get("a"), Some(&Value::string("a")));
|
||||
assert_eq!(result.get("b"), Some(&Value::string("b")));
|
||||
assert_eq!(result.get_field_value("a"), Some(&Value::string("a")));
|
||||
assert_eq!(result.get_field_value("b"), Some(&Value::string("b")));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn anonymous_inline_fragment_include_false() {
|
||||
run_query("{ a, ... @include(if: false) { b } }", |result| {
|
||||
assert_eq!(result.get("a"), Some(&Value::string("a")));
|
||||
assert_eq!(result.get("b"), None);
|
||||
assert_eq!(result.get_field_value("a"), Some(&Value::string("a")));
|
||||
assert_eq!(result.get_field_value("b"), None);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn anonymous_inline_fragment_skip_false() {
|
||||
run_query("{ a, ... @skip(if: false) { b } }", |result| {
|
||||
assert_eq!(result.get("a"), Some(&Value::string("a")));
|
||||
assert_eq!(result.get("b"), Some(&Value::string("b")));
|
||||
assert_eq!(result.get_field_value("a"), Some(&Value::string("a")));
|
||||
assert_eq!(result.get_field_value("b"), Some(&Value::string("b")));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn anonymous_inline_fragment_skip_true() {
|
||||
run_query("{ a, ... @skip(if: true) { b } }", |result| {
|
||||
assert_eq!(result.get("a"), Some(&Value::string("a")));
|
||||
assert_eq!(result.get("b"), None);
|
||||
assert_eq!(result.get_field_value("a"), Some(&Value::string("a")));
|
||||
assert_eq!(result.get_field_value("b"), None);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn scalar_include_true_skip_true() {
|
||||
run_query("{ a, b @include(if: true) @skip(if: true) }", |result| {
|
||||
assert_eq!(result.get("a"), Some(&Value::string("a")));
|
||||
assert_eq!(result.get("b"), None);
|
||||
assert_eq!(result.get_field_value("a"), Some(&Value::string("a")));
|
||||
assert_eq!(result.get_field_value("b"), None);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn scalar_include_true_skip_false() {
|
||||
run_query("{ a, b @include(if: true) @skip(if: false) }", |result| {
|
||||
assert_eq!(result.get("a"), Some(&Value::string("a")));
|
||||
assert_eq!(result.get("b"), Some(&Value::string("b")));
|
||||
assert_eq!(result.get_field_value("a"), Some(&Value::string("a")));
|
||||
assert_eq!(result.get_field_value("b"), Some(&Value::string("b")));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn scalar_include_false_skip_true() {
|
||||
run_query("{ a, b @include(if: false) @skip(if: true) }", |result| {
|
||||
assert_eq!(result.get("a"), Some(&Value::string("a")));
|
||||
assert_eq!(result.get("b"), None);
|
||||
assert_eq!(result.get_field_value("a"), Some(&Value::string("a")));
|
||||
assert_eq!(result.get_field_value("b"), None);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn scalar_include_false_skip_false() {
|
||||
run_query("{ a, b @include(if: false) @skip(if: false) }", |result| {
|
||||
assert_eq!(result.get("a"), Some(&Value::string("a")));
|
||||
assert_eq!(result.get("b"), None);
|
||||
assert_eq!(result.get_field_value("a"), Some(&Value::string("a")));
|
||||
assert_eq!(result.get_field_value("b"), None);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
use indexmap::IndexMap;
|
||||
|
||||
use ast::InputValue;
|
||||
use executor::Variables;
|
||||
use parser::SourcePosition;
|
||||
use schema::model::RootNode;
|
||||
use types::scalars::EmptyMutation;
|
||||
use validation::RuleError;
|
||||
use value::Value;
|
||||
use value::{Value, Object};
|
||||
use GraphQLError::ValidationError;
|
||||
|
||||
#[derive(GraphQLEnum, Debug)]
|
||||
|
@ -30,7 +28,7 @@ graphql_object!(TestType: () |&self| {
|
|||
|
||||
fn run_variable_query<F>(query: &str, vars: Variables, f: F)
|
||||
where
|
||||
F: Fn(&IndexMap<String, Value>) -> (),
|
||||
F: Fn(&Object) -> (),
|
||||
{
|
||||
let schema = RootNode::new(TestType, EmptyMutation::<()>::new());
|
||||
|
||||
|
@ -47,7 +45,7 @@ where
|
|||
|
||||
fn run_query<F>(query: &str, f: F)
|
||||
where
|
||||
F: Fn(&IndexMap<String, Value>) -> (),
|
||||
F: Fn(&Object) -> (),
|
||||
{
|
||||
run_variable_query(query, Variables::new(), f);
|
||||
}
|
||||
|
@ -55,14 +53,14 @@ where
|
|||
#[test]
|
||||
fn accepts_enum_literal() {
|
||||
run_query("{ toString(color: RED) }", |result| {
|
||||
assert_eq!(result.get("toString"), Some(&Value::string("Color::Red")));
|
||||
assert_eq!(result.get_field_value("toString"), Some(&Value::string("Color::Red")));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn serializes_as_output() {
|
||||
run_query("{ aColor }", |result| {
|
||||
assert_eq!(result.get("aColor"), Some(&Value::string("RED")));
|
||||
assert_eq!(result.get_field_value("aColor"), Some(&Value::string("RED")));
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -92,7 +90,7 @@ fn accepts_strings_in_variables() {
|
|||
.into_iter()
|
||||
.collect(),
|
||||
|result| {
|
||||
assert_eq!(result.get("toString"), Some(&Value::string("Color::Red")));
|
||||
assert_eq!(result.get_field_value("toString"), Some(&Value::string("Color::Red")));
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
use indexmap::IndexMap;
|
||||
|
||||
use executor::Variables;
|
||||
use schema::model::RootNode;
|
||||
use types::scalars::EmptyMutation;
|
||||
use value::Value;
|
||||
use value::{Value, Object};
|
||||
|
||||
/*
|
||||
|
||||
|
@ -76,7 +74,7 @@ graphql_object!(Root: () |&self| {
|
|||
|
||||
fn run_type_info_query<F>(doc: &str, f: F)
|
||||
where
|
||||
F: Fn((&IndexMap<String, Value>, &Vec<Value>)) -> (),
|
||||
F: Fn((&Object, &Vec<Value>)) -> (),
|
||||
{
|
||||
let schema = RootNode::new(Root {}, EmptyMutation::<()>::new());
|
||||
|
||||
|
@ -90,13 +88,13 @@ where
|
|||
let type_info = result
|
||||
.as_object_value()
|
||||
.expect("Result is not an object")
|
||||
.get("__type")
|
||||
.get_field_value("__type")
|
||||
.expect("__type field missing")
|
||||
.as_object_value()
|
||||
.expect("__type field not an object value");
|
||||
|
||||
let values = type_info
|
||||
.get("enumValues")
|
||||
.get_field_value("enumValues")
|
||||
.expect("enumValues field missing")
|
||||
.as_list_value()
|
||||
.expect("enumValues not a list");
|
||||
|
@ -122,8 +120,8 @@ fn default_name_introspection() {
|
|||
"#;
|
||||
|
||||
run_type_info_query(doc, |(type_info, values)| {
|
||||
assert_eq!(type_info.get("name"), Some(&Value::string("DefaultName")));
|
||||
assert_eq!(type_info.get("description"), Some(&Value::null()));
|
||||
assert_eq!(type_info.get_field_value("name"), Some(&Value::string("DefaultName")));
|
||||
assert_eq!(type_info.get_field_value("description"), Some(&Value::null()));
|
||||
|
||||
assert_eq!(values.len(), 2);
|
||||
|
||||
|
@ -171,8 +169,8 @@ fn named_introspection() {
|
|||
"#;
|
||||
|
||||
run_type_info_query(doc, |(type_info, values)| {
|
||||
assert_eq!(type_info.get("name"), Some(&Value::string("ANamedEnum")));
|
||||
assert_eq!(type_info.get("description"), Some(&Value::null()));
|
||||
assert_eq!(type_info.get_field_value("name"), Some(&Value::string("ANamedEnum")));
|
||||
assert_eq!(type_info.get_field_value("description"), Some(&Value::null()));
|
||||
|
||||
assert_eq!(values.len(), 2);
|
||||
|
||||
|
@ -221,10 +219,10 @@ fn no_trailing_comma_introspection() {
|
|||
|
||||
run_type_info_query(doc, |(type_info, values)| {
|
||||
assert_eq!(
|
||||
type_info.get("name"),
|
||||
type_info.get_field_value("name"),
|
||||
Some(&Value::string("NoTrailingComma"))
|
||||
);
|
||||
assert_eq!(type_info.get("description"), Some(&Value::null()));
|
||||
assert_eq!(type_info.get_field_value("description"), Some(&Value::null()));
|
||||
|
||||
assert_eq!(values.len(), 2);
|
||||
|
||||
|
@ -273,11 +271,11 @@ fn enum_description_introspection() {
|
|||
|
||||
run_type_info_query(doc, |(type_info, values)| {
|
||||
assert_eq!(
|
||||
type_info.get("name"),
|
||||
type_info.get_field_value("name"),
|
||||
Some(&Value::string("EnumDescription"))
|
||||
);
|
||||
assert_eq!(
|
||||
type_info.get("description"),
|
||||
type_info.get_field_value("description"),
|
||||
Some(&Value::string("A description of the enum itself"))
|
||||
);
|
||||
|
||||
|
@ -328,10 +326,10 @@ fn enum_value_description_introspection() {
|
|||
|
||||
run_type_info_query(doc, |(type_info, values)| {
|
||||
assert_eq!(
|
||||
type_info.get("name"),
|
||||
type_info.get_field_value("name"),
|
||||
Some(&Value::string("EnumValueDescription"))
|
||||
);
|
||||
assert_eq!(type_info.get("description"), Some(&Value::null()));
|
||||
assert_eq!(type_info.get_field_value("description"), Some(&Value::null()));
|
||||
|
||||
assert_eq!(values.len(), 2);
|
||||
|
||||
|
@ -380,10 +378,10 @@ fn enum_deprecation_introspection() {
|
|||
|
||||
run_type_info_query(doc, |(type_info, values)| {
|
||||
assert_eq!(
|
||||
type_info.get("name"),
|
||||
type_info.get_field_value("name"),
|
||||
Some(&Value::string("EnumDeprecation"))
|
||||
);
|
||||
assert_eq!(type_info.get("description"), Some(&Value::null()));
|
||||
assert_eq!(type_info.get_field_value("description"), Some(&Value::null()));
|
||||
|
||||
assert_eq!(values.len(), 2);
|
||||
|
||||
|
@ -438,10 +436,10 @@ fn enum_deprecation_no_values_introspection() {
|
|||
|
||||
run_type_info_query(doc, |(type_info, values)| {
|
||||
assert_eq!(
|
||||
type_info.get("name"),
|
||||
type_info.get_field_value("name"),
|
||||
Some(&Value::string("EnumDeprecation"))
|
||||
);
|
||||
assert_eq!(type_info.get("description"), Some(&Value::null()));
|
||||
assert_eq!(type_info.get_field_value("description"), Some(&Value::null()));
|
||||
|
||||
assert_eq!(values.len(), 0);
|
||||
});
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
use indexmap::IndexMap;
|
||||
|
||||
use ast::{FromInputValue, InputValue};
|
||||
use executor::Variables;
|
||||
use schema::model::RootNode;
|
||||
use types::scalars::EmptyMutation;
|
||||
use value::Value;
|
||||
use value::{Value, Object};
|
||||
|
||||
struct Root;
|
||||
|
||||
|
@ -106,7 +104,7 @@ graphql_object!(Root: () |&self| {
|
|||
|
||||
fn run_type_info_query<F>(doc: &str, f: F)
|
||||
where
|
||||
F: Fn(&IndexMap<String, Value>, &Vec<Value>) -> (),
|
||||
F: Fn(&Object, &Vec<Value>) -> (),
|
||||
{
|
||||
let schema = RootNode::new(Root {}, EmptyMutation::<()>::new());
|
||||
|
||||
|
@ -120,13 +118,13 @@ where
|
|||
let type_info = result
|
||||
.as_object_value()
|
||||
.expect("Result is not an object")
|
||||
.get("__type")
|
||||
.get_field_value("__type")
|
||||
.expect("__type field missing")
|
||||
.as_object_value()
|
||||
.expect("__type field not an object value");
|
||||
|
||||
let fields = type_info
|
||||
.get("inputFields")
|
||||
.get_field_value("inputFields")
|
||||
.expect("inputFields field missing")
|
||||
.as_list_value()
|
||||
.expect("inputFields not a list");
|
||||
|
@ -156,8 +154,8 @@ fn default_name_introspection() {
|
|||
"#;
|
||||
|
||||
run_type_info_query(doc, |type_info, fields| {
|
||||
assert_eq!(type_info.get("name"), Some(&Value::string("DefaultName")));
|
||||
assert_eq!(type_info.get("description"), Some(&Value::null()));
|
||||
assert_eq!(type_info.get_field_value("name"), Some(&Value::string("DefaultName")));
|
||||
assert_eq!(type_info.get_field_value("description"), Some(&Value::null()));
|
||||
|
||||
assert_eq!(fields.len(), 2);
|
||||
|
||||
|
@ -256,10 +254,10 @@ fn no_trailing_comma_introspection() {
|
|||
|
||||
run_type_info_query(doc, |type_info, fields| {
|
||||
assert_eq!(
|
||||
type_info.get("name"),
|
||||
type_info.get_field_value("name"),
|
||||
Some(&Value::string("NoTrailingComma"))
|
||||
);
|
||||
assert_eq!(type_info.get("description"), Some(&Value::null()));
|
||||
assert_eq!(type_info.get_field_value("description"), Some(&Value::null()));
|
||||
|
||||
assert_eq!(fields.len(), 2);
|
||||
|
||||
|
@ -337,8 +335,8 @@ fn derive_introspection() {
|
|||
"#;
|
||||
|
||||
run_type_info_query(doc, |type_info, fields| {
|
||||
assert_eq!(type_info.get("name"), Some(&Value::string("Derive")));
|
||||
assert_eq!(type_info.get("description"), Some(&Value::null()));
|
||||
assert_eq!(type_info.get_field_value("name"), Some(&Value::string("Derive")));
|
||||
assert_eq!(type_info.get_field_value("description"), Some(&Value::null()));
|
||||
|
||||
assert_eq!(fields.len(), 1);
|
||||
|
||||
|
@ -405,10 +403,10 @@ fn named_introspection() {
|
|||
|
||||
run_type_info_query(doc, |type_info, fields| {
|
||||
assert_eq!(
|
||||
type_info.get("name"),
|
||||
type_info.get_field_value("name"),
|
||||
Some(&Value::string("ANamedInputObject"))
|
||||
);
|
||||
assert_eq!(type_info.get("description"), Some(&Value::null()));
|
||||
assert_eq!(type_info.get_field_value("description"), Some(&Value::null()));
|
||||
|
||||
assert_eq!(fields.len(), 1);
|
||||
|
||||
|
@ -461,9 +459,9 @@ fn description_introspection() {
|
|||
"#;
|
||||
|
||||
run_type_info_query(doc, |type_info, fields| {
|
||||
assert_eq!(type_info.get("name"), Some(&Value::string("Description")));
|
||||
assert_eq!(type_info.get_field_value("name"), Some(&Value::string("Description")));
|
||||
assert_eq!(
|
||||
type_info.get("description"),
|
||||
type_info.get_field_value("description"),
|
||||
Some(&Value::string("Description for the input object"))
|
||||
);
|
||||
|
||||
|
@ -519,10 +517,10 @@ fn field_description_introspection() {
|
|||
|
||||
run_type_info_query(doc, |type_info, fields| {
|
||||
assert_eq!(
|
||||
type_info.get("name"),
|
||||
type_info.get_field_value("name"),
|
||||
Some(&Value::string("FieldDescription"))
|
||||
);
|
||||
assert_eq!(type_info.get("description"), Some(&Value::null()));
|
||||
assert_eq!(type_info.get_field_value("description"), Some(&Value::null()));
|
||||
|
||||
assert_eq!(fields.len(), 2);
|
||||
|
||||
|
@ -597,7 +595,7 @@ fn field_with_defaults_introspection() {
|
|||
|
||||
run_type_info_query(doc, |type_info, fields| {
|
||||
assert_eq!(
|
||||
type_info.get("name"),
|
||||
type_info.get_field_value("name"),
|
||||
Some(&Value::string("FieldWithDefaults"))
|
||||
);
|
||||
|
||||
|
|
|
@ -126,21 +126,39 @@ fn enum_introspection() {
|
|||
let type_info = result
|
||||
.as_object_value()
|
||||
.expect("Result is not an object")
|
||||
.get("__type")
|
||||
.get_field_value("__type")
|
||||
.expect("__type field missing")
|
||||
.as_object_value()
|
||||
.expect("__type field not an object value");
|
||||
|
||||
assert_eq!(type_info.get("name"), Some(&Value::string("SampleEnum")));
|
||||
assert_eq!(type_info.get("kind"), Some(&Value::string("ENUM")));
|
||||
assert_eq!(type_info.get("description"), Some(&Value::null()));
|
||||
assert_eq!(type_info.get("interfaces"), Some(&Value::null()));
|
||||
assert_eq!(type_info.get("possibleTypes"), Some(&Value::null()));
|
||||
assert_eq!(type_info.get("inputFields"), Some(&Value::null()));
|
||||
assert_eq!(type_info.get("ofType"), Some(&Value::null()));
|
||||
assert_eq!(
|
||||
type_info.get_field_value("name"),
|
||||
Some(&Value::string("SampleEnum"))
|
||||
);
|
||||
assert_eq!(
|
||||
type_info.get_field_value("kind"),
|
||||
Some(&Value::string("ENUM"))
|
||||
);
|
||||
assert_eq!(
|
||||
type_info.get_field_value("description"),
|
||||
Some(&Value::null())
|
||||
);
|
||||
assert_eq!(
|
||||
type_info.get_field_value("interfaces"),
|
||||
Some(&Value::null())
|
||||
);
|
||||
assert_eq!(
|
||||
type_info.get_field_value("possibleTypes"),
|
||||
Some(&Value::null())
|
||||
);
|
||||
assert_eq!(
|
||||
type_info.get_field_value("inputFields"),
|
||||
Some(&Value::null())
|
||||
);
|
||||
assert_eq!(type_info.get_field_value("ofType"), Some(&Value::null()));
|
||||
|
||||
let values = type_info
|
||||
.get("enumValues")
|
||||
.get_field_value("enumValues")
|
||||
.expect("enumValues field missing")
|
||||
.as_list_value()
|
||||
.expect("enumValues not a list");
|
||||
|
@ -219,27 +237,39 @@ fn interface_introspection() {
|
|||
let type_info = result
|
||||
.as_object_value()
|
||||
.expect("Result is not an object")
|
||||
.get("__type")
|
||||
.get_field_value("__type")
|
||||
.expect("__type field missing")
|
||||
.as_object_value()
|
||||
.expect("__type field not an object value");
|
||||
|
||||
assert_eq!(
|
||||
type_info.get("name"),
|
||||
type_info.get_field_value("name"),
|
||||
Some(&Value::string("SampleInterface"))
|
||||
);
|
||||
assert_eq!(type_info.get("kind"), Some(&Value::string("INTERFACE")));
|
||||
assert_eq!(
|
||||
type_info.get("description"),
|
||||
type_info.get_field_value("kind"),
|
||||
Some(&Value::string("INTERFACE"))
|
||||
);
|
||||
assert_eq!(
|
||||
type_info.get_field_value("description"),
|
||||
Some(&Value::string("A sample interface"))
|
||||
);
|
||||
assert_eq!(type_info.get("interfaces"), Some(&Value::null()));
|
||||
assert_eq!(type_info.get("enumValues"), Some(&Value::null()));
|
||||
assert_eq!(type_info.get("inputFields"), Some(&Value::null()));
|
||||
assert_eq!(type_info.get("ofType"), Some(&Value::null()));
|
||||
assert_eq!(
|
||||
type_info.get_field_value("interfaces"),
|
||||
Some(&Value::null())
|
||||
);
|
||||
assert_eq!(
|
||||
type_info.get_field_value("enumValues"),
|
||||
Some(&Value::null())
|
||||
);
|
||||
assert_eq!(
|
||||
type_info.get_field_value("inputFields"),
|
||||
Some(&Value::null())
|
||||
);
|
||||
assert_eq!(type_info.get_field_value("ofType"), Some(&Value::null()));
|
||||
|
||||
let possible_types = type_info
|
||||
.get("possibleTypes")
|
||||
.get_field_value("possibleTypes")
|
||||
.expect("possibleTypes field missing")
|
||||
.as_list_value()
|
||||
.expect("possibleTypes not a list");
|
||||
|
@ -251,7 +281,7 @@ fn interface_introspection() {
|
|||
)));
|
||||
|
||||
let fields = type_info
|
||||
.get("fields")
|
||||
.get_field_value("fields")
|
||||
.expect("fields field missing")
|
||||
.as_list_value()
|
||||
.expect("fields field not an object value");
|
||||
|
@ -353,32 +383,47 @@ fn object_introspection() {
|
|||
let type_info = result
|
||||
.as_object_value()
|
||||
.expect("Result is not an object")
|
||||
.get("__type")
|
||||
.get_field_value("__type")
|
||||
.expect("__type field missing")
|
||||
.as_object_value()
|
||||
.expect("__type field not an object value");
|
||||
|
||||
assert_eq!(type_info.get("name"), Some(&Value::string("Root")));
|
||||
assert_eq!(type_info.get("kind"), Some(&Value::string("OBJECT")));
|
||||
assert_eq!(
|
||||
type_info.get("description"),
|
||||
type_info.get_field_value("name"),
|
||||
Some(&Value::string("Root"))
|
||||
);
|
||||
assert_eq!(
|
||||
type_info.get_field_value("kind"),
|
||||
Some(&Value::string("OBJECT"))
|
||||
);
|
||||
assert_eq!(
|
||||
type_info.get_field_value("description"),
|
||||
Some(&Value::string("The root query object in the schema"))
|
||||
);
|
||||
assert_eq!(
|
||||
type_info.get("interfaces"),
|
||||
type_info.get_field_value("interfaces"),
|
||||
Some(&Value::list(vec![Value::object(
|
||||
vec![("name", Value::string("SampleInterface"))]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
)]))
|
||||
);
|
||||
assert_eq!(type_info.get("enumValues"), Some(&Value::null()));
|
||||
assert_eq!(type_info.get("inputFields"), Some(&Value::null()));
|
||||
assert_eq!(type_info.get("ofType"), Some(&Value::null()));
|
||||
assert_eq!(type_info.get("possibleTypes"), Some(&Value::null()));
|
||||
assert_eq!(
|
||||
type_info.get_field_value("enumValues"),
|
||||
Some(&Value::null())
|
||||
);
|
||||
assert_eq!(
|
||||
type_info.get_field_value("inputFields"),
|
||||
Some(&Value::null())
|
||||
);
|
||||
assert_eq!(type_info.get_field_value("ofType"), Some(&Value::null()));
|
||||
assert_eq!(
|
||||
type_info.get_field_value("possibleTypes"),
|
||||
Some(&Value::null())
|
||||
);
|
||||
|
||||
let fields = type_info
|
||||
.get("fields")
|
||||
.get_field_value("fields")
|
||||
.expect("fields field missing")
|
||||
.as_list_value()
|
||||
.expect("fields field not an object value");
|
||||
|
@ -538,7 +583,7 @@ fn scalar_introspection() {
|
|||
let type_info = result
|
||||
.as_object_value()
|
||||
.expect("Result is not an object")
|
||||
.get("__type")
|
||||
.get_field_value("__type")
|
||||
.expect("__type field missing");
|
||||
|
||||
assert_eq!(
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
use indexmap::IndexMap;
|
||||
|
||||
use ast::InputValue;
|
||||
use executor::Variables;
|
||||
use parser::SourcePosition;
|
||||
use schema::model::RootNode;
|
||||
use types::scalars::EmptyMutation;
|
||||
use validation::RuleError;
|
||||
use value::Value;
|
||||
use value::{Value, Object};
|
||||
use GraphQLError::ValidationError;
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -116,7 +114,7 @@ graphql_object!(TestType: () |&self| {
|
|||
|
||||
fn run_variable_query<F>(query: &str, vars: Variables, f: F)
|
||||
where
|
||||
F: Fn(&IndexMap<String, Value>) -> (),
|
||||
F: Fn(&Object) -> (),
|
||||
{
|
||||
let schema = RootNode::new(TestType, EmptyMutation::<()>::new());
|
||||
|
||||
|
@ -133,7 +131,7 @@ where
|
|||
|
||||
fn run_query<F>(query: &str, f: F)
|
||||
where
|
||||
F: Fn(&IndexMap<String, Value>) -> (),
|
||||
F: Fn(&Object) -> (),
|
||||
{
|
||||
run_variable_query(query, Variables::new(), f);
|
||||
}
|
||||
|
@ -144,7 +142,7 @@ fn inline_complex_input() {
|
|||
r#"{ fieldWithObjectInput(input: {a: "foo", b: ["bar"], c: "baz"}) }"#,
|
||||
|result| {
|
||||
assert_eq!(
|
||||
result.get("fieldWithObjectInput"),
|
||||
result.get_field_value("fieldWithObjectInput"),
|
||||
Some(&Value::string(r#"Some(TestInputObject { a: Some("foo"), b: Some([Some("bar")]), c: "baz", d: None })"#)));
|
||||
},
|
||||
);
|
||||
|
@ -156,7 +154,7 @@ fn inline_parse_single_value_to_list() {
|
|||
r#"{ fieldWithObjectInput(input: {a: "foo", b: "bar", c: "baz"}) }"#,
|
||||
|result| {
|
||||
assert_eq!(
|
||||
result.get("fieldWithObjectInput"),
|
||||
result.get_field_value("fieldWithObjectInput"),
|
||||
Some(&Value::string(r#"Some(TestInputObject { a: Some("foo"), b: Some([Some("bar")]), c: "baz", d: None })"#)));
|
||||
},
|
||||
);
|
||||
|
@ -168,7 +166,7 @@ fn inline_runs_from_input_value_on_scalar() {
|
|||
r#"{ fieldWithObjectInput(input: {c: "baz", d: "SerializedValue"}) }"#,
|
||||
|result| {
|
||||
assert_eq!(
|
||||
result.get("fieldWithObjectInput"),
|
||||
result.get_field_value("fieldWithObjectInput"),
|
||||
Some(&Value::string(r#"Some(TestInputObject { a: None, b: None, c: "baz", d: Some(TestComplexScalar) })"#)));
|
||||
},
|
||||
);
|
||||
|
@ -192,7 +190,7 @@ fn variable_complex_input() {
|
|||
.collect(),
|
||||
|result| {
|
||||
assert_eq!(
|
||||
result.get("fieldWithObjectInput"),
|
||||
result.get_field_value("fieldWithObjectInput"),
|
||||
Some(&Value::string(r#"Some(TestInputObject { a: Some("foo"), b: Some([Some("bar")]), c: "baz", d: None })"#)));
|
||||
},
|
||||
);
|
||||
|
@ -216,7 +214,7 @@ fn variable_parse_single_value_to_list() {
|
|||
.collect(),
|
||||
|result| {
|
||||
assert_eq!(
|
||||
result.get("fieldWithObjectInput"),
|
||||
result.get_field_value("fieldWithObjectInput"),
|
||||
Some(&Value::string(r#"Some(TestInputObject { a: Some("foo"), b: Some([Some("bar")]), c: "baz", d: None })"#)));
|
||||
},
|
||||
);
|
||||
|
@ -239,7 +237,7 @@ fn variable_runs_from_input_value_on_scalar() {
|
|||
.collect(),
|
||||
|result| {
|
||||
assert_eq!(
|
||||
result.get("fieldWithObjectInput"),
|
||||
result.get_field_value("fieldWithObjectInput"),
|
||||
Some(&Value::string(r#"Some(TestInputObject { a: None, b: None, c: "baz", d: Some(TestComplexScalar) })"#)));
|
||||
},
|
||||
);
|
||||
|
@ -387,7 +385,7 @@ fn variable_error_on_additional_field() {
|
|||
fn allow_nullable_inputs_to_be_omitted() {
|
||||
run_query(r#"{ fieldWithNullableStringInput }"#, |result| {
|
||||
assert_eq!(
|
||||
result.get("fieldWithNullableStringInput"),
|
||||
result.get_field_value("fieldWithNullableStringInput"),
|
||||
Some(&Value::string(r#"None"#))
|
||||
);
|
||||
});
|
||||
|
@ -399,7 +397,7 @@ fn allow_nullable_inputs_to_be_omitted_in_variable() {
|
|||
r#"query q($value: String) { fieldWithNullableStringInput(input: $value) }"#,
|
||||
|result| {
|
||||
assert_eq!(
|
||||
result.get("fieldWithNullableStringInput"),
|
||||
result.get_field_value("fieldWithNullableStringInput"),
|
||||
Some(&Value::string(r#"None"#))
|
||||
);
|
||||
},
|
||||
|
@ -412,7 +410,7 @@ fn allow_nullable_inputs_to_be_explicitly_null() {
|
|||
r#"{ fieldWithNullableStringInput(input: null) }"#,
|
||||
|result| {
|
||||
assert_eq!(
|
||||
result.get("fieldWithNullableStringInput"),
|
||||
result.get_field_value("fieldWithNullableStringInput"),
|
||||
Some(&Value::string(r#"None"#))
|
||||
);
|
||||
},
|
||||
|
@ -428,7 +426,7 @@ fn allow_nullable_inputs_to_be_set_to_null_in_variable() {
|
|||
.collect(),
|
||||
|result| {
|
||||
assert_eq!(
|
||||
result.get("fieldWithNullableStringInput"),
|
||||
result.get_field_value("fieldWithNullableStringInput"),
|
||||
Some(&Value::string(r#"None"#))
|
||||
);
|
||||
},
|
||||
|
@ -444,7 +442,7 @@ fn allow_nullable_inputs_to_be_set_to_value_in_variable() {
|
|||
.collect(),
|
||||
|result| {
|
||||
assert_eq!(
|
||||
result.get("fieldWithNullableStringInput"),
|
||||
result.get_field_value("fieldWithNullableStringInput"),
|
||||
Some(&Value::string(r#"Some("a")"#))
|
||||
);
|
||||
},
|
||||
|
@ -457,7 +455,7 @@ fn allow_nullable_inputs_to_be_set_to_value_directly() {
|
|||
r#"{ fieldWithNullableStringInput(input: "a") }"#,
|
||||
|result| {
|
||||
assert_eq!(
|
||||
result.get("fieldWithNullableStringInput"),
|
||||
result.get_field_value("fieldWithNullableStringInput"),
|
||||
Some(&Value::string(r#"Some("a")"#))
|
||||
);
|
||||
},
|
||||
|
@ -511,7 +509,7 @@ fn allow_non_nullable_inputs_to_be_set_to_value_in_variable() {
|
|||
.collect(),
|
||||
|result| {
|
||||
assert_eq!(
|
||||
result.get("fieldWithNonNullableStringInput"),
|
||||
result.get_field_value("fieldWithNonNullableStringInput"),
|
||||
Some(&Value::string(r#""a""#))
|
||||
);
|
||||
},
|
||||
|
@ -524,7 +522,7 @@ fn allow_non_nullable_inputs_to_be_set_to_value_directly() {
|
|||
r#"{ fieldWithNonNullableStringInput(input: "a") }"#,
|
||||
|result| {
|
||||
assert_eq!(
|
||||
result.get("fieldWithNonNullableStringInput"),
|
||||
result.get_field_value("fieldWithNonNullableStringInput"),
|
||||
Some(&Value::string(r#""a""#))
|
||||
);
|
||||
},
|
||||
|
@ -539,7 +537,7 @@ fn allow_lists_to_be_null() {
|
|||
.into_iter()
|
||||
.collect(),
|
||||
|result| {
|
||||
assert_eq!(result.get("list"), Some(&Value::string(r#"None"#)));
|
||||
assert_eq!(result.get_field_value("list"), Some(&Value::string(r#"None"#)));
|
||||
},
|
||||
);
|
||||
}
|
||||
|
@ -555,7 +553,7 @@ fn allow_lists_to_contain_values() {
|
|||
.collect(),
|
||||
|result| {
|
||||
assert_eq!(
|
||||
result.get("list"),
|
||||
result.get_field_value("list"),
|
||||
Some(&Value::string(r#"Some([Some("A")])"#))
|
||||
);
|
||||
},
|
||||
|
@ -577,7 +575,7 @@ fn allow_lists_to_contain_null() {
|
|||
.collect(),
|
||||
|result| {
|
||||
assert_eq!(
|
||||
result.get("list"),
|
||||
result.get_field_value("list"),
|
||||
Some(&Value::string(r#"Some([Some("A"), None, Some("B")])"#))
|
||||
);
|
||||
},
|
||||
|
@ -614,7 +612,7 @@ fn allow_non_null_lists_to_contain_values() {
|
|||
)].into_iter()
|
||||
.collect(),
|
||||
|result| {
|
||||
assert_eq!(result.get("nnList"), Some(&Value::string(r#"[Some("A")]"#)));
|
||||
assert_eq!(result.get_field_value("nnList"), Some(&Value::string(r#"[Some("A")]"#)));
|
||||
},
|
||||
);
|
||||
}
|
||||
|
@ -633,7 +631,7 @@ fn allow_non_null_lists_to_contain_null() {
|
|||
.collect(),
|
||||
|result| {
|
||||
assert_eq!(
|
||||
result.get("nnList"),
|
||||
result.get_field_value("nnList"),
|
||||
Some(&Value::string(r#"[Some("A"), None, Some("B")]"#))
|
||||
);
|
||||
},
|
||||
|
@ -648,7 +646,7 @@ fn allow_lists_of_non_null_to_be_null() {
|
|||
.into_iter()
|
||||
.collect(),
|
||||
|result| {
|
||||
assert_eq!(result.get("listNn"), Some(&Value::string(r#"None"#)));
|
||||
assert_eq!(result.get_field_value("listNn"), Some(&Value::string(r#"None"#)));
|
||||
},
|
||||
);
|
||||
}
|
||||
|
@ -663,7 +661,7 @@ fn allow_lists_of_non_null_to_contain_values() {
|
|||
)].into_iter()
|
||||
.collect(),
|
||||
|result| {
|
||||
assert_eq!(result.get("listNn"), Some(&Value::string(r#"Some(["A"])"#)));
|
||||
assert_eq!(result.get_field_value("listNn"), Some(&Value::string(r#"Some(["A"])"#)));
|
||||
},
|
||||
);
|
||||
}
|
||||
|
@ -748,7 +746,7 @@ fn allow_non_null_lists_of_non_null_to_contain_values() {
|
|||
)].into_iter()
|
||||
.collect(),
|
||||
|result| {
|
||||
assert_eq!(result.get("nnListNn"), Some(&Value::string(r#"["A"]"#)));
|
||||
assert_eq!(result.get_field_value("nnListNn"), Some(&Value::string(r#"["A"]"#)));
|
||||
},
|
||||
);
|
||||
}
|
||||
|
@ -799,7 +797,7 @@ fn does_not_allow_unknown_types_to_be_used_as_values() {
|
|||
fn default_argument_when_not_provided() {
|
||||
run_query(r#"{ fieldWithDefaultArgumentValue }"#, |result| {
|
||||
assert_eq!(
|
||||
result.get("fieldWithDefaultArgumentValue"),
|
||||
result.get_field_value("fieldWithDefaultArgumentValue"),
|
||||
Some(&Value::string(r#""Hello World""#))
|
||||
);
|
||||
});
|
||||
|
@ -811,7 +809,7 @@ fn default_argument_when_nullable_variable_not_provided() {
|
|||
r#"query q($input: String) { fieldWithDefaultArgumentValue(input: $input) }"#,
|
||||
|result| {
|
||||
assert_eq!(
|
||||
result.get("fieldWithDefaultArgumentValue"),
|
||||
result.get_field_value("fieldWithDefaultArgumentValue"),
|
||||
Some(&Value::string(r#""Hello World""#))
|
||||
);
|
||||
},
|
||||
|
@ -827,7 +825,7 @@ fn default_argument_when_nullable_variable_set_to_null() {
|
|||
.collect(),
|
||||
|result| {
|
||||
assert_eq!(
|
||||
result.get("fieldWithDefaultArgumentValue"),
|
||||
result.get_field_value("fieldWithDefaultArgumentValue"),
|
||||
Some(&Value::string(r#""Hello World""#))
|
||||
);
|
||||
},
|
||||
|
@ -838,14 +836,14 @@ fn default_argument_when_nullable_variable_set_to_null() {
|
|||
fn nullable_input_object_arguments_successful_without_variables() {
|
||||
run_query(r#"{ exampleInput(arg: {a: "abc", b: 123}) }"#, |result| {
|
||||
assert_eq!(
|
||||
result.get("exampleInput"),
|
||||
result.get_field_value("exampleInput"),
|
||||
Some(&Value::string(r#"a: Some("abc"), b: 123"#))
|
||||
);
|
||||
});
|
||||
|
||||
run_query(r#"{ exampleInput(arg: {a: null, b: 1}) }"#, |result| {
|
||||
assert_eq!(
|
||||
result.get("exampleInput"),
|
||||
result.get_field_value("exampleInput"),
|
||||
Some(&Value::string(r#"a: None, b: 1"#))
|
||||
);
|
||||
});
|
||||
|
@ -860,7 +858,7 @@ fn nullable_input_object_arguments_successful_with_variables() {
|
|||
.collect(),
|
||||
|result| {
|
||||
assert_eq!(
|
||||
result.get("exampleInput"),
|
||||
result.get_field_value("exampleInput"),
|
||||
Some(&Value::string(r#"a: None, b: 123"#))
|
||||
);
|
||||
},
|
||||
|
@ -873,7 +871,7 @@ fn nullable_input_object_arguments_successful_with_variables() {
|
|||
.collect(),
|
||||
|result| {
|
||||
assert_eq!(
|
||||
result.get("exampleInput"),
|
||||
result.get_field_value("exampleInput"),
|
||||
Some(&Value::string(r#"a: None, b: 1"#))
|
||||
);
|
||||
},
|
||||
|
@ -884,7 +882,7 @@ fn nullable_input_object_arguments_successful_with_variables() {
|
|||
vec![].into_iter().collect(),
|
||||
|result| {
|
||||
assert_eq!(
|
||||
result.get("exampleInput"),
|
||||
result.get_field_value("exampleInput"),
|
||||
Some(&Value::string(r#"a: None, b: 1"#))
|
||||
);
|
||||
},
|
||||
|
@ -969,7 +967,7 @@ fn does_not_allow_null_variable_for_required_field() {
|
|||
fn input_object_with_default_values() {
|
||||
run_query(r#"{ inputWithDefaults(arg: {a: 1}) }"#, |result| {
|
||||
assert_eq!(
|
||||
result.get("inputWithDefaults"),
|
||||
result.get_field_value("inputWithDefaults"),
|
||||
Some(&Value::string(r#"a: 1"#))
|
||||
);
|
||||
});
|
||||
|
@ -981,7 +979,7 @@ fn input_object_with_default_values() {
|
|||
.collect(),
|
||||
|result| {
|
||||
assert_eq!(
|
||||
result.get("inputWithDefaults"),
|
||||
result.get_field_value("inputWithDefaults"),
|
||||
Some(&Value::string(r#"a: 1"#))
|
||||
);
|
||||
},
|
||||
|
@ -992,7 +990,7 @@ fn input_object_with_default_values() {
|
|||
vec![].into_iter().collect(),
|
||||
|result| {
|
||||
assert_eq!(
|
||||
result.get("inputWithDefaults"),
|
||||
result.get_field_value("inputWithDefaults"),
|
||||
Some(&Value::string(r#"a: 1"#))
|
||||
);
|
||||
},
|
||||
|
@ -1005,7 +1003,7 @@ fn input_object_with_default_values() {
|
|||
.collect(),
|
||||
|result| {
|
||||
assert_eq!(
|
||||
result.get("inputWithDefaults"),
|
||||
result.get_field_value("inputWithDefaults"),
|
||||
Some(&Value::string(r#"a: 2"#))
|
||||
);
|
||||
},
|
||||
|
@ -1024,7 +1022,7 @@ mod integers {
|
|||
.collect(),
|
||||
|result| {
|
||||
assert_eq!(
|
||||
result.get("integerInput"),
|
||||
result.get_field_value("integerInput"),
|
||||
Some(&Value::string(r#"value: 1"#))
|
||||
);
|
||||
},
|
||||
|
@ -1037,7 +1035,7 @@ mod integers {
|
|||
.collect(),
|
||||
|result| {
|
||||
assert_eq!(
|
||||
result.get("integerInput"),
|
||||
result.get_field_value("integerInput"),
|
||||
Some(&Value::string(r#"value: -1"#))
|
||||
);
|
||||
},
|
||||
|
@ -1097,7 +1095,7 @@ mod floats {
|
|||
.collect(),
|
||||
|result| {
|
||||
assert_eq!(
|
||||
result.get("floatInput"),
|
||||
result.get_field_value("floatInput"),
|
||||
Some(&Value::string(r#"value: 10"#))
|
||||
);
|
||||
},
|
||||
|
@ -1113,7 +1111,7 @@ mod floats {
|
|||
.collect(),
|
||||
|result| {
|
||||
assert_eq!(
|
||||
result.get("floatInput"),
|
||||
result.get_field_value("floatInput"),
|
||||
Some(&Value::string(r#"value: -1"#))
|
||||
);
|
||||
},
|
||||
|
|
|
@ -8,7 +8,7 @@ use ast::InputValue;
|
|||
use executor::ExecutionError;
|
||||
use parser::{ParseError, SourcePosition, Spanning};
|
||||
use validation::RuleError;
|
||||
use {GraphQLError, Value};
|
||||
use {GraphQLError, Object, Value};
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct SerializeHelper {
|
||||
|
@ -250,6 +250,22 @@ impl<'a> ser::Serialize for Spanning<ParseError<'a>> {
|
|||
}
|
||||
}
|
||||
|
||||
impl ser::Serialize for Object {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: ser::Serializer,
|
||||
{
|
||||
let mut map = serializer.serialize_map(Some(self.field_count()))?;
|
||||
|
||||
for &(ref f, ref v) in self.iter() {
|
||||
map.serialize_key(f)?;
|
||||
map.serialize_value(v)?;
|
||||
}
|
||||
|
||||
map.end()
|
||||
}
|
||||
}
|
||||
|
||||
impl ser::Serialize for Value {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
|
|
|
@ -162,7 +162,7 @@ pub use schema::model::RootNode;
|
|||
pub use types::base::{Arguments, GraphQLType, TypeKind};
|
||||
pub use types::scalars::{EmptyMutation, ID};
|
||||
pub use validation::RuleError;
|
||||
pub use value::Value;
|
||||
pub use value::{Value, Object};
|
||||
|
||||
pub use schema::meta;
|
||||
|
||||
|
|
|
@ -112,13 +112,13 @@ where
|
|||
let type_info = result
|
||||
.as_object_value()
|
||||
.expect("Result is not an object")
|
||||
.get("__type")
|
||||
.get_field_value("__type")
|
||||
.expect("__type field missing")
|
||||
.as_object_value()
|
||||
.expect("__type field not an object value");
|
||||
|
||||
let fields = type_info
|
||||
.get("fields")
|
||||
.get_field_value("fields")
|
||||
.expect("fields field missing")
|
||||
.as_list_value()
|
||||
.expect("fields not a list");
|
||||
|
@ -128,7 +128,7 @@ where
|
|||
.filter(|f| {
|
||||
f.as_object_value()
|
||||
.expect("Field not an object")
|
||||
.get("name")
|
||||
.get_field_value("name")
|
||||
.expect("name field missing from field")
|
||||
.as_string_value()
|
||||
.expect("name is not a string") == field_name
|
||||
|
@ -141,7 +141,7 @@ where
|
|||
println!("Field: {:?}", field);
|
||||
|
||||
let args = field
|
||||
.get("args")
|
||||
.get_field_value("args")
|
||||
.expect("args missing from field")
|
||||
.as_list_value()
|
||||
.expect("args is not a list");
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
use indexmap::IndexMap;
|
||||
|
||||
use ast::InputValue;
|
||||
use executor::FieldResult;
|
||||
use schema::model::RootNode;
|
||||
use types::scalars::EmptyMutation;
|
||||
use value::Value;
|
||||
use value::{Object, Value};
|
||||
|
||||
struct Interface;
|
||||
struct Root;
|
||||
|
@ -59,7 +57,7 @@ graphql_interface!(Interface: () |&self| {
|
|||
|
||||
fn run_field_info_query<F>(type_name: &str, field_name: &str, f: F)
|
||||
where
|
||||
F: Fn(&IndexMap<String, Value>) -> (),
|
||||
F: Fn(&Object) -> (),
|
||||
{
|
||||
let doc = r#"
|
||||
query ($typeName: String!) {
|
||||
|
@ -87,13 +85,13 @@ where
|
|||
let type_info = result
|
||||
.as_object_value()
|
||||
.expect("Result is not an object")
|
||||
.get("__type")
|
||||
.get_field_value("__type")
|
||||
.expect("__type field missing")
|
||||
.as_object_value()
|
||||
.expect("__type field not an object value");
|
||||
|
||||
let fields = type_info
|
||||
.get("fields")
|
||||
.get_field_value("fields")
|
||||
.expect("fields field missing")
|
||||
.as_list_value()
|
||||
.expect("fields not a list");
|
||||
|
@ -103,7 +101,7 @@ where
|
|||
.filter(|f| {
|
||||
f.as_object_value()
|
||||
.expect("Field not an object")
|
||||
.get("name")
|
||||
.get_field_value("name")
|
||||
.expect("name field missing from field")
|
||||
.as_string_value()
|
||||
.expect("name is not a string") == field_name
|
||||
|
@ -121,57 +119,78 @@ where
|
|||
#[test]
|
||||
fn introspect_object_field_simple() {
|
||||
run_field_info_query("Root", "simple", |field| {
|
||||
assert_eq!(field.get("name"), Some(&Value::string("simple")));
|
||||
assert_eq!(field.get("description"), Some(&Value::null()));
|
||||
assert_eq!(field.get("isDeprecated"), Some(&Value::boolean(false)));
|
||||
assert_eq!(field.get("deprecationReason"), Some(&Value::null()));
|
||||
assert_eq!(
|
||||
field.get_field_value("name"),
|
||||
Some(&Value::string("simple"))
|
||||
);
|
||||
assert_eq!(field.get_field_value("description"), Some(&Value::null()));
|
||||
assert_eq!(
|
||||
field.get_field_value("isDeprecated"),
|
||||
Some(&Value::boolean(false))
|
||||
);
|
||||
assert_eq!(
|
||||
field.get_field_value("deprecationReason"),
|
||||
Some(&Value::null())
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn introspect_interface_field_simple() {
|
||||
run_field_info_query("Interface", "simple", |field| {
|
||||
assert_eq!(field.get("name"), Some(&Value::string("simple")));
|
||||
assert_eq!(field.get("description"), Some(&Value::null()));
|
||||
assert_eq!(field.get("isDeprecated"), Some(&Value::boolean(false)));
|
||||
assert_eq!(field.get("deprecationReason"), Some(&Value::null()));
|
||||
assert_eq!(
|
||||
field.get_field_value("name"),
|
||||
Some(&Value::string("simple"))
|
||||
);
|
||||
assert_eq!(field.get_field_value("description"), Some(&Value::null()));
|
||||
assert_eq!(
|
||||
field.get_field_value("isDeprecated"),
|
||||
Some(&Value::boolean(false))
|
||||
);
|
||||
assert_eq!(
|
||||
field.get_field_value("deprecationReason"),
|
||||
Some(&Value::null())
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn introspect_object_field_description() {
|
||||
run_field_info_query("Root", "description", |field| {
|
||||
assert_eq!(field.get("name"), Some(&Value::string("description")));
|
||||
assert_eq!(
|
||||
field.get("description"),
|
||||
field.get_field_value("name"),
|
||||
Some(&Value::string("description"))
|
||||
);
|
||||
assert_eq!(
|
||||
field.get_field_value("description"),
|
||||
Some(&Value::string("Field description"))
|
||||
);
|
||||
assert_eq!(field.get("isDeprecated"), Some(&Value::boolean(false)));
|
||||
assert_eq!(field.get("deprecationReason"), Some(&Value::null()));
|
||||
assert_eq!(field.get_field_value("isDeprecated"), Some(&Value::boolean(false)));
|
||||
assert_eq!(field.get_field_value("deprecationReason"), Some(&Value::null()));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn introspect_interface_field_description() {
|
||||
run_field_info_query("Interface", "description", |field| {
|
||||
assert_eq!(field.get("name"), Some(&Value::string("description")));
|
||||
assert_eq!(field.get_field_value("name"), Some(&Value::string("description")));
|
||||
assert_eq!(
|
||||
field.get("description"),
|
||||
field.get_field_value("description"),
|
||||
Some(&Value::string("Field description"))
|
||||
);
|
||||
assert_eq!(field.get("isDeprecated"), Some(&Value::boolean(false)));
|
||||
assert_eq!(field.get("deprecationReason"), Some(&Value::null()));
|
||||
assert_eq!(field.get_field_value("isDeprecated"), Some(&Value::boolean(false)));
|
||||
assert_eq!(field.get_field_value("deprecationReason"), Some(&Value::null()));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn introspect_object_field_deprecated() {
|
||||
run_field_info_query("Root", "deprecated", |field| {
|
||||
assert_eq!(field.get("name"), Some(&Value::string("deprecated")));
|
||||
assert_eq!(field.get("description"), Some(&Value::null()));
|
||||
assert_eq!(field.get("isDeprecated"), Some(&Value::boolean(true)));
|
||||
assert_eq!(field.get_field_value("name"), Some(&Value::string("deprecated")));
|
||||
assert_eq!(field.get_field_value("description"), Some(&Value::null()));
|
||||
assert_eq!(field.get_field_value("isDeprecated"), Some(&Value::boolean(true)));
|
||||
assert_eq!(
|
||||
field.get("deprecationReason"),
|
||||
field.get_field_value("deprecationReason"),
|
||||
Some(&Value::string("Deprecation reason"))
|
||||
);
|
||||
});
|
||||
|
@ -180,11 +199,11 @@ fn introspect_object_field_deprecated() {
|
|||
#[test]
|
||||
fn introspect_interface_field_deprecated() {
|
||||
run_field_info_query("Interface", "deprecated", |field| {
|
||||
assert_eq!(field.get("name"), Some(&Value::string("deprecated")));
|
||||
assert_eq!(field.get("description"), Some(&Value::null()));
|
||||
assert_eq!(field.get("isDeprecated"), Some(&Value::boolean(true)));
|
||||
assert_eq!(field.get_field_value("name"), Some(&Value::string("deprecated")));
|
||||
assert_eq!(field.get_field_value("description"), Some(&Value::null()));
|
||||
assert_eq!(field.get_field_value("isDeprecated"), Some(&Value::boolean(true)));
|
||||
assert_eq!(
|
||||
field.get("deprecationReason"),
|
||||
field.get_field_value("deprecationReason"),
|
||||
Some(&Value::string("Deprecation reason"))
|
||||
);
|
||||
});
|
||||
|
@ -193,14 +212,14 @@ fn introspect_interface_field_deprecated() {
|
|||
#[test]
|
||||
fn introspect_object_field_deprecated_descr() {
|
||||
run_field_info_query("Root", "deprecatedDescr", |field| {
|
||||
assert_eq!(field.get("name"), Some(&Value::string("deprecatedDescr")));
|
||||
assert_eq!(field.get_field_value("name"), Some(&Value::string("deprecatedDescr")));
|
||||
assert_eq!(
|
||||
field.get("description"),
|
||||
field.get_field_value("description"),
|
||||
Some(&Value::string("Field description"))
|
||||
);
|
||||
assert_eq!(field.get("isDeprecated"), Some(&Value::boolean(true)));
|
||||
assert_eq!(field.get_field_value("isDeprecated"), Some(&Value::boolean(true)));
|
||||
assert_eq!(
|
||||
field.get("deprecationReason"),
|
||||
field.get_field_value("deprecationReason"),
|
||||
Some(&Value::string("Deprecation reason"))
|
||||
);
|
||||
});
|
||||
|
@ -209,14 +228,14 @@ fn introspect_object_field_deprecated_descr() {
|
|||
#[test]
|
||||
fn introspect_interface_field_deprecated_descr() {
|
||||
run_field_info_query("Interface", "deprecatedDescr", |field| {
|
||||
assert_eq!(field.get("name"), Some(&Value::string("deprecatedDescr")));
|
||||
assert_eq!(field.get_field_value("name"), Some(&Value::string("deprecatedDescr")));
|
||||
assert_eq!(
|
||||
field.get("description"),
|
||||
field.get_field_value("description"),
|
||||
Some(&Value::string("Field description"))
|
||||
);
|
||||
assert_eq!(field.get("isDeprecated"), Some(&Value::boolean(true)));
|
||||
assert_eq!(field.get_field_value("isDeprecated"), Some(&Value::boolean(true)));
|
||||
assert_eq!(
|
||||
field.get("deprecationReason"),
|
||||
field.get_field_value("deprecationReason"),
|
||||
Some(&Value::string("Deprecation reason"))
|
||||
);
|
||||
});
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
use indexmap::IndexMap;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use ast::InputValue;
|
||||
use schema::model::RootNode;
|
||||
use types::scalars::EmptyMutation;
|
||||
use value::Value;
|
||||
use value::{Value, Object};
|
||||
|
||||
/*
|
||||
|
||||
|
@ -130,7 +129,7 @@ graphql_object!(<'a> Root: () as "Root" |&self| {
|
|||
|
||||
fn run_type_info_query<F>(type_name: &str, f: F)
|
||||
where
|
||||
F: Fn(&IndexMap<String, Value>, &Vec<Value>) -> (),
|
||||
F: Fn(&Object, &Vec<Value>) -> (),
|
||||
{
|
||||
let doc = r#"
|
||||
query ($typeName: String!) {
|
||||
|
@ -157,13 +156,13 @@ where
|
|||
let type_info = result
|
||||
.as_object_value()
|
||||
.expect("Result is not an object")
|
||||
.get("__type")
|
||||
.get_field_value("__type")
|
||||
.expect("__type field missing")
|
||||
.as_object_value()
|
||||
.expect("__type field not an object value");
|
||||
|
||||
let fields = type_info
|
||||
.get("fields")
|
||||
.get_field_value("fields")
|
||||
.expect("fields field missing")
|
||||
.as_list_value()
|
||||
.expect("fields field not a list value");
|
||||
|
@ -175,10 +174,10 @@ where
|
|||
fn introspect_custom_name() {
|
||||
run_type_info_query("ACustomNamedInterface", |object, fields| {
|
||||
assert_eq!(
|
||||
object.get("name"),
|
||||
object.get_field_value("name"),
|
||||
Some(&Value::string("ACustomNamedInterface"))
|
||||
);
|
||||
assert_eq!(object.get("description"), Some(&Value::null()));
|
||||
assert_eq!(object.get_field_value("description"), Some(&Value::null()));
|
||||
|
||||
assert!(
|
||||
fields.contains(&Value::object(
|
||||
|
@ -193,8 +192,8 @@ fn introspect_custom_name() {
|
|||
#[test]
|
||||
fn introspect_with_lifetime() {
|
||||
run_type_info_query("WithLifetime", |object, fields| {
|
||||
assert_eq!(object.get("name"), Some(&Value::string("WithLifetime")));
|
||||
assert_eq!(object.get("description"), Some(&Value::null()));
|
||||
assert_eq!(object.get_field_value("name"), Some(&Value::string("WithLifetime")));
|
||||
assert_eq!(object.get_field_value("description"), Some(&Value::null()));
|
||||
|
||||
assert!(
|
||||
fields.contains(&Value::object(
|
||||
|
@ -209,8 +208,8 @@ fn introspect_with_lifetime() {
|
|||
#[test]
|
||||
fn introspect_with_generics() {
|
||||
run_type_info_query("WithGenerics", |object, fields| {
|
||||
assert_eq!(object.get("name"), Some(&Value::string("WithGenerics")));
|
||||
assert_eq!(object.get("description"), Some(&Value::null()));
|
||||
assert_eq!(object.get_field_value("name"), Some(&Value::string("WithGenerics")));
|
||||
assert_eq!(object.get_field_value("description"), Some(&Value::null()));
|
||||
|
||||
assert!(
|
||||
fields.contains(&Value::object(
|
||||
|
@ -225,9 +224,9 @@ fn introspect_with_generics() {
|
|||
#[test]
|
||||
fn introspect_description_first() {
|
||||
run_type_info_query("DescriptionFirst", |object, fields| {
|
||||
assert_eq!(object.get("name"), Some(&Value::string("DescriptionFirst")));
|
||||
assert_eq!(object.get_field_value("name"), Some(&Value::string("DescriptionFirst")));
|
||||
assert_eq!(
|
||||
object.get("description"),
|
||||
object.get_field_value("description"),
|
||||
Some(&Value::string("A description"))
|
||||
);
|
||||
|
||||
|
@ -244,9 +243,9 @@ fn introspect_description_first() {
|
|||
#[test]
|
||||
fn introspect_fields_first() {
|
||||
run_type_info_query("FieldsFirst", |object, fields| {
|
||||
assert_eq!(object.get("name"), Some(&Value::string("FieldsFirst")));
|
||||
assert_eq!(object.get_field_value("name"), Some(&Value::string("FieldsFirst")));
|
||||
assert_eq!(
|
||||
object.get("description"),
|
||||
object.get_field_value("description"),
|
||||
Some(&Value::string("A description"))
|
||||
);
|
||||
|
||||
|
@ -263,9 +262,9 @@ fn introspect_fields_first() {
|
|||
#[test]
|
||||
fn introspect_interfaces_first() {
|
||||
run_type_info_query("InterfacesFirst", |object, fields| {
|
||||
assert_eq!(object.get("name"), Some(&Value::string("InterfacesFirst")));
|
||||
assert_eq!(object.get_field_value("name"), Some(&Value::string("InterfacesFirst")));
|
||||
assert_eq!(
|
||||
object.get("description"),
|
||||
object.get_field_value("description"),
|
||||
Some(&Value::string("A description"))
|
||||
);
|
||||
|
||||
|
@ -283,11 +282,11 @@ fn introspect_interfaces_first() {
|
|||
fn introspect_commas_with_trailing() {
|
||||
run_type_info_query("CommasWithTrailing", |object, fields| {
|
||||
assert_eq!(
|
||||
object.get("name"),
|
||||
object.get_field_value("name"),
|
||||
Some(&Value::string("CommasWithTrailing"))
|
||||
);
|
||||
assert_eq!(
|
||||
object.get("description"),
|
||||
object.get_field_value("description"),
|
||||
Some(&Value::string("A description"))
|
||||
);
|
||||
|
||||
|
@ -304,9 +303,9 @@ fn introspect_commas_with_trailing() {
|
|||
#[test]
|
||||
fn introspect_commas_on_meta() {
|
||||
run_type_info_query("CommasOnMeta", |object, fields| {
|
||||
assert_eq!(object.get("name"), Some(&Value::string("CommasOnMeta")));
|
||||
assert_eq!(object.get_field_value("name"), Some(&Value::string("CommasOnMeta")));
|
||||
assert_eq!(
|
||||
object.get("description"),
|
||||
object.get_field_value("description"),
|
||||
Some(&Value::string("A description"))
|
||||
);
|
||||
|
||||
|
@ -324,11 +323,11 @@ fn introspect_commas_on_meta() {
|
|||
fn introspect_resolvers_with_trailing_comma() {
|
||||
run_type_info_query("ResolversWithTrailingComma", |object, fields| {
|
||||
assert_eq!(
|
||||
object.get("name"),
|
||||
object.get_field_value("name"),
|
||||
Some(&Value::string("ResolversWithTrailingComma"))
|
||||
);
|
||||
assert_eq!(
|
||||
object.get("description"),
|
||||
object.get_field_value("description"),
|
||||
Some(&Value::string("A description"))
|
||||
);
|
||||
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
use indexmap::IndexMap;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use ast::InputValue;
|
||||
use executor::{Context, FieldResult};
|
||||
use schema::model::RootNode;
|
||||
use types::scalars::EmptyMutation;
|
||||
use value::Value;
|
||||
use value::{Object, Value};
|
||||
|
||||
/*
|
||||
|
||||
|
@ -144,7 +143,7 @@ graphql_object!(<'a> Root: InnerContext as "Root" |&self| {
|
|||
|
||||
fn run_type_info_query<F>(type_name: &str, f: F)
|
||||
where
|
||||
F: Fn(&IndexMap<String, Value>, &Vec<Value>) -> (),
|
||||
F: Fn(&Object, &Vec<Value>) -> (),
|
||||
{
|
||||
let doc = r#"
|
||||
query ($typeName: String!) {
|
||||
|
@ -184,13 +183,13 @@ where
|
|||
let type_info = result
|
||||
.as_object_value()
|
||||
.expect("Result is not an object")
|
||||
.get("__type")
|
||||
.get_field_value("__type")
|
||||
.expect("__type field missing")
|
||||
.as_object_value()
|
||||
.expect("__type field not an object value");
|
||||
|
||||
let fields = type_info
|
||||
.get("fields")
|
||||
.get_field_value("fields")
|
||||
.expect("fields field missing")
|
||||
.as_list_value()
|
||||
.expect("fields field not a list value");
|
||||
|
@ -201,12 +200,18 @@ where
|
|||
#[test]
|
||||
fn introspect_custom_name() {
|
||||
run_type_info_query("ACustomNamedType", |object, fields| {
|
||||
assert_eq!(object.get("name"), Some(&Value::string("ACustomNamedType")));
|
||||
assert_eq!(object.get("description"), Some(&Value::null()));
|
||||
assert_eq!(object.get("interfaces"), Some(&Value::list(vec![])));
|
||||
assert_eq!(
|
||||
object.get_field_value("name"),
|
||||
Some(&Value::string("ACustomNamedType"))
|
||||
);
|
||||
assert_eq!(object.get_field_value("description"), Some(&Value::null()));
|
||||
assert_eq!(
|
||||
object.get_field_value("interfaces"),
|
||||
Some(&Value::list(vec![]))
|
||||
);
|
||||
|
||||
assert!(fields.contains(&graphql_value!({
|
||||
"name": "simple",
|
||||
"name": "simple",
|
||||
"type": { "kind": "NON_NULL", "name": None, "ofType": { "kind": "SCALAR", "name": "Int" } }
|
||||
})));
|
||||
});
|
||||
|
@ -215,12 +220,18 @@ fn introspect_custom_name() {
|
|||
#[test]
|
||||
fn introspect_with_lifetime() {
|
||||
run_type_info_query("WithLifetime", |object, fields| {
|
||||
assert_eq!(object.get("name"), Some(&Value::string("WithLifetime")));
|
||||
assert_eq!(object.get("description"), Some(&Value::null()));
|
||||
assert_eq!(object.get("interfaces"), Some(&Value::list(vec![])));
|
||||
assert_eq!(
|
||||
object.get_field_value("name"),
|
||||
Some(&Value::string("WithLifetime"))
|
||||
);
|
||||
assert_eq!(object.get_field_value("description"), Some(&Value::null()));
|
||||
assert_eq!(
|
||||
object.get_field_value("interfaces"),
|
||||
Some(&Value::list(vec![]))
|
||||
);
|
||||
|
||||
assert!(fields.contains(&graphql_value!({
|
||||
"name": "simple",
|
||||
"name": "simple",
|
||||
"type": { "kind": "NON_NULL", "name": None, "ofType": { "kind": "SCALAR", "name": "Int" } }
|
||||
})));
|
||||
});
|
||||
|
@ -229,12 +240,18 @@ fn introspect_with_lifetime() {
|
|||
#[test]
|
||||
fn introspect_with_generics() {
|
||||
run_type_info_query("WithGenerics", |object, fields| {
|
||||
assert_eq!(object.get("name"), Some(&Value::string("WithGenerics")));
|
||||
assert_eq!(object.get("description"), Some(&Value::null()));
|
||||
assert_eq!(object.get("interfaces"), Some(&Value::list(vec![])));
|
||||
assert_eq!(
|
||||
object.get_field_value("name"),
|
||||
Some(&Value::string("WithGenerics"))
|
||||
);
|
||||
assert_eq!(object.get_field_value("description"), Some(&Value::null()));
|
||||
assert_eq!(
|
||||
object.get_field_value("interfaces"),
|
||||
Some(&Value::list(vec![]))
|
||||
);
|
||||
|
||||
assert!(fields.contains(&graphql_value!({
|
||||
"name": "simple",
|
||||
"name": "simple",
|
||||
"type": { "kind": "NON_NULL", "name": None, "ofType": { "kind": "SCALAR", "name": "Int" } }
|
||||
})));
|
||||
});
|
||||
|
@ -243,13 +260,16 @@ fn introspect_with_generics() {
|
|||
#[test]
|
||||
fn introspect_description_first() {
|
||||
run_type_info_query("DescriptionFirst", |object, fields| {
|
||||
assert_eq!(object.get("name"), Some(&Value::string("DescriptionFirst")));
|
||||
assert_eq!(
|
||||
object.get("description"),
|
||||
object.get_field_value("name"),
|
||||
Some(&Value::string("DescriptionFirst"))
|
||||
);
|
||||
assert_eq!(
|
||||
object.get_field_value("description"),
|
||||
Some(&Value::string("A description"))
|
||||
);
|
||||
assert_eq!(
|
||||
object.get("interfaces"),
|
||||
object.get_field_value("interfaces"),
|
||||
Some(&Value::list(vec![Value::object(
|
||||
vec![
|
||||
("name", Value::string("Interface")),
|
||||
|
@ -260,7 +280,7 @@ fn introspect_description_first() {
|
|||
);
|
||||
|
||||
assert!(fields.contains(&graphql_value!({
|
||||
"name": "simple",
|
||||
"name": "simple",
|
||||
"type": { "kind": "NON_NULL", "name": None, "ofType": { "kind": "SCALAR", "name": "Int" } }
|
||||
})));
|
||||
});
|
||||
|
@ -269,13 +289,16 @@ fn introspect_description_first() {
|
|||
#[test]
|
||||
fn introspect_fields_first() {
|
||||
run_type_info_query("FieldsFirst", |object, fields| {
|
||||
assert_eq!(object.get("name"), Some(&Value::string("FieldsFirst")));
|
||||
assert_eq!(
|
||||
object.get("description"),
|
||||
object.get_field_value("name"),
|
||||
Some(&Value::string("FieldsFirst"))
|
||||
);
|
||||
assert_eq!(
|
||||
object.get_field_value("description"),
|
||||
Some(&Value::string("A description"))
|
||||
);
|
||||
assert_eq!(
|
||||
object.get("interfaces"),
|
||||
object.get_field_value("interfaces"),
|
||||
Some(&Value::list(vec![Value::object(
|
||||
vec![
|
||||
("name", Value::string("Interface")),
|
||||
|
@ -286,7 +309,7 @@ fn introspect_fields_first() {
|
|||
);
|
||||
|
||||
assert!(fields.contains(&graphql_value!({
|
||||
"name": "simple",
|
||||
"name": "simple",
|
||||
"type": { "kind": "NON_NULL", "name": None, "ofType": { "kind": "SCALAR", "name": "Int" } }
|
||||
})));
|
||||
});
|
||||
|
@ -295,13 +318,16 @@ fn introspect_fields_first() {
|
|||
#[test]
|
||||
fn introspect_interfaces_first() {
|
||||
run_type_info_query("InterfacesFirst", |object, fields| {
|
||||
assert_eq!(object.get("name"), Some(&Value::string("InterfacesFirst")));
|
||||
assert_eq!(
|
||||
object.get("description"),
|
||||
object.get_field_value("name"),
|
||||
Some(&Value::string("InterfacesFirst"))
|
||||
);
|
||||
assert_eq!(
|
||||
object.get_field_value("description"),
|
||||
Some(&Value::string("A description"))
|
||||
);
|
||||
assert_eq!(
|
||||
object.get("interfaces"),
|
||||
object.get_field_value("interfaces"),
|
||||
Some(&Value::list(vec![Value::object(
|
||||
vec![
|
||||
("name", Value::string("Interface")),
|
||||
|
@ -312,7 +338,7 @@ fn introspect_interfaces_first() {
|
|||
);
|
||||
|
||||
assert!(fields.contains(&graphql_value!({
|
||||
"name": "simple",
|
||||
"name": "simple",
|
||||
"type": { "kind": "NON_NULL", "name": None, "ofType": { "kind": "SCALAR", "name": "Int" } }
|
||||
})));
|
||||
});
|
||||
|
@ -322,15 +348,15 @@ fn introspect_interfaces_first() {
|
|||
fn introspect_commas_with_trailing() {
|
||||
run_type_info_query("CommasWithTrailing", |object, fields| {
|
||||
assert_eq!(
|
||||
object.get("name"),
|
||||
object.get_field_value("name"),
|
||||
Some(&Value::string("CommasWithTrailing"))
|
||||
);
|
||||
assert_eq!(
|
||||
object.get("description"),
|
||||
object.get_field_value("description"),
|
||||
Some(&Value::string("A description"))
|
||||
);
|
||||
assert_eq!(
|
||||
object.get("interfaces"),
|
||||
object.get_field_value("interfaces"),
|
||||
Some(&Value::list(vec![Value::object(
|
||||
vec![
|
||||
("name", Value::string("Interface")),
|
||||
|
@ -341,7 +367,7 @@ fn introspect_commas_with_trailing() {
|
|||
);
|
||||
|
||||
assert!(fields.contains(&graphql_value!({
|
||||
"name": "simple",
|
||||
"name": "simple",
|
||||
"type": { "kind": "NON_NULL", "name": None, "ofType": { "kind": "SCALAR", "name": "Int" } }
|
||||
})));
|
||||
});
|
||||
|
@ -350,13 +376,16 @@ fn introspect_commas_with_trailing() {
|
|||
#[test]
|
||||
fn introspect_commas_on_meta() {
|
||||
run_type_info_query("CommasOnMeta", |object, fields| {
|
||||
assert_eq!(object.get("name"), Some(&Value::string("CommasOnMeta")));
|
||||
assert_eq!(
|
||||
object.get("description"),
|
||||
object.get_field_value("name"),
|
||||
Some(&Value::string("CommasOnMeta"))
|
||||
);
|
||||
assert_eq!(
|
||||
object.get_field_value("description"),
|
||||
Some(&Value::string("A description"))
|
||||
);
|
||||
assert_eq!(
|
||||
object.get("interfaces"),
|
||||
object.get_field_value("interfaces"),
|
||||
Some(&Value::list(vec![Value::object(
|
||||
vec![
|
||||
("name", Value::string("Interface")),
|
||||
|
@ -367,7 +396,7 @@ fn introspect_commas_on_meta() {
|
|||
);
|
||||
|
||||
assert!(fields.contains(&graphql_value!({
|
||||
"name": "simple",
|
||||
"name": "simple",
|
||||
"type": { "kind": "NON_NULL", "name": None, "ofType": { "kind": "SCALAR", "name": "Int" } }
|
||||
})));
|
||||
});
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
use indexmap::IndexMap;
|
||||
|
||||
use executor::Variables;
|
||||
use schema::model::RootNode;
|
||||
use types::scalars::EmptyMutation;
|
||||
use value::Value;
|
||||
use value::{Value, Object};
|
||||
|
||||
struct DefaultName(i32);
|
||||
struct OtherOrder(i32);
|
||||
|
@ -72,7 +70,7 @@ graphql_object!(Root: () |&self| {
|
|||
|
||||
fn run_type_info_query<F>(doc: &str, f: F)
|
||||
where
|
||||
F: Fn(&IndexMap<String, Value>) -> (),
|
||||
F: Fn(&Object) -> (),
|
||||
{
|
||||
let schema = RootNode::new(Root {}, EmptyMutation::<()>::new());
|
||||
|
||||
|
@ -86,7 +84,7 @@ where
|
|||
let type_info = result
|
||||
.as_object_value()
|
||||
.expect("Result is not an object")
|
||||
.get("__type")
|
||||
.get_field_value("__type")
|
||||
.expect("__type field missing")
|
||||
.as_object_value()
|
||||
.expect("__type field not an object value");
|
||||
|
@ -106,8 +104,8 @@ fn default_name_introspection() {
|
|||
"#;
|
||||
|
||||
run_type_info_query(doc, |type_info| {
|
||||
assert_eq!(type_info.get("name"), Some(&Value::string("DefaultName")));
|
||||
assert_eq!(type_info.get("description"), Some(&Value::null()));
|
||||
assert_eq!(type_info.get_field_value("name"), Some(&Value::string("DefaultName")));
|
||||
assert_eq!(type_info.get_field_value("description"), Some(&Value::null()));
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -123,8 +121,8 @@ fn other_order_introspection() {
|
|||
"#;
|
||||
|
||||
run_type_info_query(doc, |type_info| {
|
||||
assert_eq!(type_info.get("name"), Some(&Value::string("OtherOrder")));
|
||||
assert_eq!(type_info.get("description"), Some(&Value::null()));
|
||||
assert_eq!(type_info.get_field_value("name"), Some(&Value::string("OtherOrder")));
|
||||
assert_eq!(type_info.get_field_value("description"), Some(&Value::null()));
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -140,8 +138,8 @@ fn named_introspection() {
|
|||
"#;
|
||||
|
||||
run_type_info_query(doc, |type_info| {
|
||||
assert_eq!(type_info.get("name"), Some(&Value::string("ANamedScalar")));
|
||||
assert_eq!(type_info.get("description"), Some(&Value::null()));
|
||||
assert_eq!(type_info.get_field_value("name"), Some(&Value::string("ANamedScalar")));
|
||||
assert_eq!(type_info.get_field_value("description"), Some(&Value::null()));
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -158,11 +156,11 @@ fn scalar_description_introspection() {
|
|||
|
||||
run_type_info_query(doc, |type_info| {
|
||||
assert_eq!(
|
||||
type_info.get("name"),
|
||||
type_info.get_field_value("name"),
|
||||
Some(&Value::string("ScalarDescription"))
|
||||
);
|
||||
assert_eq!(
|
||||
type_info.get("description"),
|
||||
type_info.get_field_value("description"),
|
||||
Some(&Value::string("A sample scalar, represented as an integer"))
|
||||
);
|
||||
});
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
use indexmap::IndexMap;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use ast::InputValue;
|
||||
use schema::model::RootNode;
|
||||
use types::scalars::EmptyMutation;
|
||||
use value::Value;
|
||||
use value::{Value, Object};
|
||||
|
||||
/*
|
||||
|
||||
|
@ -111,7 +110,7 @@ graphql_object!(<'a> Root: () as "Root" |&self| {
|
|||
|
||||
fn run_type_info_query<F>(type_name: &str, f: F)
|
||||
where
|
||||
F: Fn(&IndexMap<String, Value>, &Vec<Value>) -> (),
|
||||
F: Fn(&Object, &Vec<Value>) -> (),
|
||||
{
|
||||
let doc = r#"
|
||||
query ($typeName: String!) {
|
||||
|
@ -138,13 +137,13 @@ where
|
|||
let type_info = result
|
||||
.as_object_value()
|
||||
.expect("Result is not an object")
|
||||
.get("__type")
|
||||
.get_field_value("__type")
|
||||
.expect("__type field missing")
|
||||
.as_object_value()
|
||||
.expect("__type field not an object value");
|
||||
|
||||
let possible_types = type_info
|
||||
.get("possibleTypes")
|
||||
.get_field_value("possibleTypes")
|
||||
.expect("possibleTypes field missing")
|
||||
.as_list_value()
|
||||
.expect("possibleTypes field not a list value");
|
||||
|
@ -155,8 +154,8 @@ where
|
|||
#[test]
|
||||
fn introspect_custom_name() {
|
||||
run_type_info_query("ACustomNamedUnion", |union, possible_types| {
|
||||
assert_eq!(union.get("name"), Some(&Value::string("ACustomNamedUnion")));
|
||||
assert_eq!(union.get("description"), Some(&Value::null()));
|
||||
assert_eq!(union.get_field_value("name"), Some(&Value::string("ACustomNamedUnion")));
|
||||
assert_eq!(union.get_field_value("description"), Some(&Value::null()));
|
||||
|
||||
assert!(
|
||||
possible_types.contains(&Value::object(
|
||||
|
@ -171,8 +170,8 @@ fn introspect_custom_name() {
|
|||
#[test]
|
||||
fn introspect_with_lifetime() {
|
||||
run_type_info_query("WithLifetime", |union, possible_types| {
|
||||
assert_eq!(union.get("name"), Some(&Value::string("WithLifetime")));
|
||||
assert_eq!(union.get("description"), Some(&Value::null()));
|
||||
assert_eq!(union.get_field_value("name"), Some(&Value::string("WithLifetime")));
|
||||
assert_eq!(union.get_field_value("description"), Some(&Value::null()));
|
||||
|
||||
assert!(
|
||||
possible_types.contains(&Value::object(
|
||||
|
@ -187,8 +186,8 @@ fn introspect_with_lifetime() {
|
|||
#[test]
|
||||
fn introspect_with_generics() {
|
||||
run_type_info_query("WithGenerics", |union, possible_types| {
|
||||
assert_eq!(union.get("name"), Some(&Value::string("WithGenerics")));
|
||||
assert_eq!(union.get("description"), Some(&Value::null()));
|
||||
assert_eq!(union.get_field_value("name"), Some(&Value::string("WithGenerics")));
|
||||
assert_eq!(union.get_field_value("description"), Some(&Value::null()));
|
||||
|
||||
assert!(
|
||||
possible_types.contains(&Value::object(
|
||||
|
@ -203,9 +202,9 @@ fn introspect_with_generics() {
|
|||
#[test]
|
||||
fn introspect_description_first() {
|
||||
run_type_info_query("DescriptionFirst", |union, possible_types| {
|
||||
assert_eq!(union.get("name"), Some(&Value::string("DescriptionFirst")));
|
||||
assert_eq!(union.get_field_value("name"), Some(&Value::string("DescriptionFirst")));
|
||||
assert_eq!(
|
||||
union.get("description"),
|
||||
union.get_field_value("description"),
|
||||
Some(&Value::string("A description"))
|
||||
);
|
||||
|
||||
|
@ -222,9 +221,9 @@ fn introspect_description_first() {
|
|||
#[test]
|
||||
fn introspect_resolvers_first() {
|
||||
run_type_info_query("ResolversFirst", |union, possible_types| {
|
||||
assert_eq!(union.get("name"), Some(&Value::string("ResolversFirst")));
|
||||
assert_eq!(union.get_field_value("name"), Some(&Value::string("ResolversFirst")));
|
||||
assert_eq!(
|
||||
union.get("description"),
|
||||
union.get_field_value("description"),
|
||||
Some(&Value::string("A description"))
|
||||
);
|
||||
|
||||
|
@ -242,11 +241,11 @@ fn introspect_resolvers_first() {
|
|||
fn introspect_commas_with_trailing() {
|
||||
run_type_info_query("CommasWithTrailing", |union, possible_types| {
|
||||
assert_eq!(
|
||||
union.get("name"),
|
||||
union.get_field_value("name"),
|
||||
Some(&Value::string("CommasWithTrailing"))
|
||||
);
|
||||
assert_eq!(
|
||||
union.get("description"),
|
||||
union.get_field_value("description"),
|
||||
Some(&Value::string("A description"))
|
||||
);
|
||||
|
||||
|
@ -264,11 +263,11 @@ fn introspect_commas_with_trailing() {
|
|||
fn introspect_resolvers_with_trailing_comma() {
|
||||
run_type_info_query("ResolversWithTrailingComma", |union, possible_types| {
|
||||
assert_eq!(
|
||||
union.get("name"),
|
||||
union.get_field_value("name"),
|
||||
Some(&Value::string("ResolversWithTrailingComma"))
|
||||
);
|
||||
assert_eq!(
|
||||
union.get("description"),
|
||||
union.get_field_value("description"),
|
||||
Some(&Value::string("A description"))
|
||||
);
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ use std::fmt;
|
|||
use std::hash::{Hash, Hasher};
|
||||
|
||||
/// A reference to a line and column in an input source file
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy)]
|
||||
pub struct SourcePosition {
|
||||
index: usize,
|
||||
line: usize,
|
||||
|
|
|
@ -319,6 +319,7 @@ impl<'a> SchemaType<'a> {
|
|||
}
|
||||
|
||||
impl<'a> TypeType<'a> {
|
||||
#[inline]
|
||||
pub fn to_concrete(&self) -> Option<&'a MetaType> {
|
||||
match *self {
|
||||
TypeType::Concrete(t) => Some(t),
|
||||
|
@ -326,6 +327,7 @@ impl<'a> TypeType<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn innermost_concrete(&self) -> &'a MetaType {
|
||||
match *self {
|
||||
TypeType::Concrete(t) => t,
|
||||
|
@ -333,6 +335,7 @@ impl<'a> TypeType<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn list_contents(&self) -> Option<&TypeType<'a>> {
|
||||
match *self {
|
||||
TypeType::List(ref n) => Some(n),
|
||||
|
@ -341,6 +344,7 @@ impl<'a> TypeType<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_non_null(&self) -> bool {
|
||||
match *self {
|
||||
TypeType::NonNull(_) => true,
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
use executor::{ExecutionResult, Executor, Registry};
|
||||
use types::base::{Arguments, GraphQLType, TypeKind};
|
||||
use value::Value;
|
||||
use ast::Selection;
|
||||
|
||||
use schema::meta::{
|
||||
Argument, EnumMeta, EnumValue, Field, InputObjectMeta, InterfaceMeta, MetaType, ObjectMeta,
|
||||
|
@ -43,6 +45,26 @@ where
|
|||
_ => self.query_type.resolve_field(info, field, args, executor),
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve(
|
||||
&self,
|
||||
info: &Self::TypeInfo,
|
||||
selection_set: Option<&[Selection]>,
|
||||
executor: &Executor<Self::Context>,
|
||||
) -> Value {
|
||||
use value::Object;
|
||||
use types::base::resolve_selection_set_into;
|
||||
if let Some(selection_set) = selection_set {
|
||||
let mut result = Object::with_capacity(selection_set.len());
|
||||
if resolve_selection_set_into(self, info, selection_set, executor, &mut result) {
|
||||
Value::Object(result)
|
||||
} else {
|
||||
Value::null()
|
||||
}
|
||||
} else {
|
||||
panic!("resolve() must be implemented by non-object output types");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
graphql_object!(<'a> SchemaType<'a>: SchemaType<'a> as "__Schema" |&self| {
|
||||
|
|
|
@ -198,11 +198,11 @@ fn test_possible_types() {
|
|||
let possible_types = result
|
||||
.as_object_value()
|
||||
.expect("execution result not an object")
|
||||
.get("__type")
|
||||
.get_field_value("__type")
|
||||
.expect("'__type' not present in result")
|
||||
.as_object_value()
|
||||
.expect("'__type' not an object")
|
||||
.get("possibleTypes")
|
||||
.get_field_value("possibleTypes")
|
||||
.expect("'possibleTypes' not present in '__type'")
|
||||
.as_list_value()
|
||||
.expect("'possibleTypes' not a list")
|
||||
|
@ -210,7 +210,7 @@ fn test_possible_types() {
|
|||
.map(|t| {
|
||||
t.as_object_value()
|
||||
.expect("possible type not an object")
|
||||
.get("name")
|
||||
.get_field_value("name")
|
||||
.expect("'name' not present in type")
|
||||
.as_string_value()
|
||||
.expect("'name' not a string")
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
use indexmap::map::Entry;
|
||||
use indexmap::IndexMap;
|
||||
|
||||
use ast::{Directive, FromInputValue, InputValue, Selection};
|
||||
use executor::Variables;
|
||||
use value::Value;
|
||||
use value::{Object, Value};
|
||||
|
||||
use executor::{ExecutionResult, Executor, Registry};
|
||||
use parser::Spanning;
|
||||
|
@ -310,9 +309,9 @@ pub trait GraphQLType: Sized {
|
|||
executor: &Executor<Self::Context>,
|
||||
) -> Value {
|
||||
if let Some(selection_set) = selection_set {
|
||||
let mut result = IndexMap::new();
|
||||
let mut result = Object::with_capacity(selection_set.len());
|
||||
if resolve_selection_set_into(self, info, selection_set, executor, &mut result) {
|
||||
Value::object(result)
|
||||
Value::Object(result)
|
||||
} else {
|
||||
Value::null()
|
||||
}
|
||||
|
@ -322,12 +321,12 @@ pub trait GraphQLType: Sized {
|
|||
}
|
||||
}
|
||||
|
||||
fn resolve_selection_set_into<T, CtxT>(
|
||||
pub(crate) fn resolve_selection_set_into<T, CtxT>(
|
||||
instance: &T,
|
||||
info: &T::TypeInfo,
|
||||
selection_set: &[Selection],
|
||||
executor: &Executor<CtxT>,
|
||||
result: &mut IndexMap<String, Value>,
|
||||
result: &mut Object,
|
||||
) -> bool
|
||||
where
|
||||
T: GraphQLType<Context = CtxT>,
|
||||
|
@ -352,11 +351,11 @@ where
|
|||
continue;
|
||||
}
|
||||
|
||||
let response_name = &f.alias.as_ref().unwrap_or(&f.name).item;
|
||||
let response_name = f.alias.as_ref().unwrap_or(&f.name).item;
|
||||
|
||||
if f.name.item == "__typename" {
|
||||
result.insert(
|
||||
(*response_name).to_owned(),
|
||||
result.add_field(
|
||||
response_name,
|
||||
Value::string(instance.concrete_type_name(executor.context(), info)),
|
||||
);
|
||||
continue;
|
||||
|
@ -406,7 +405,7 @@ where
|
|||
return false;
|
||||
}
|
||||
|
||||
result.insert((*response_name).to_owned(), Value::null());
|
||||
result.add_field(response_name, Value::null());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -453,8 +452,8 @@ where
|
|||
&sub_exec,
|
||||
);
|
||||
|
||||
if let Ok(Value::Object(mut hash_map)) = sub_result {
|
||||
for (k, v) in hash_map.drain(..) {
|
||||
if let Ok(Value::Object(object)) = sub_result {
|
||||
for (k, v) in object {
|
||||
merge_key_into(result, &k, v);
|
||||
}
|
||||
} else if let Err(e) = sub_result {
|
||||
|
@ -503,15 +502,16 @@ fn is_excluded(directives: &Option<Vec<Spanning<Directive>>>, vars: &Variables)
|
|||
false
|
||||
}
|
||||
|
||||
fn merge_key_into(result: &mut IndexMap<String, Value>, response_name: &str, value: Value) {
|
||||
match result.entry(response_name.to_owned()) {
|
||||
Entry::Occupied(mut e) => match e.get_mut() {
|
||||
&mut Value::Object(ref mut dest_obj) => {
|
||||
fn merge_key_into(result: &mut Object, response_name: &str, value: Value) {
|
||||
if let Some(&mut (_, ref mut e)) = result.iter_mut().find(|&&mut (ref key, _)| key == response_name)
|
||||
{
|
||||
match *e {
|
||||
Value::Object(ref mut dest_obj) => {
|
||||
if let Value::Object(src_obj) = value {
|
||||
merge_maps(dest_obj, src_obj);
|
||||
}
|
||||
}
|
||||
&mut Value::List(ref mut dest_list) => {
|
||||
Value::List(ref mut dest_list) => {
|
||||
if let Value::List(src_list) = value {
|
||||
dest_list
|
||||
.iter_mut()
|
||||
|
@ -527,19 +527,18 @@ fn merge_key_into(result: &mut IndexMap<String, Value>, response_name: &str, val
|
|||
}
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
Entry::Vacant(e) => {
|
||||
e.insert(value);
|
||||
}
|
||||
return;
|
||||
}
|
||||
result.add_field(response_name, value);
|
||||
}
|
||||
|
||||
fn merge_maps(dest: &mut IndexMap<String, Value>, src: IndexMap<String, Value>) {
|
||||
fn merge_maps(dest: &mut Object, src: Object) {
|
||||
for (key, value) in src {
|
||||
if dest.contains_key(&key) {
|
||||
if dest.contains_field(&key) {
|
||||
merge_key_into(dest, &key, value);
|
||||
} else {
|
||||
dest.insert(key, value);
|
||||
dest.add_field(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -152,18 +152,18 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
fn resolve_into_list<T: GraphQLType, I: Iterator<Item = T>>(
|
||||
executor: &Executor<T::Context>,
|
||||
info: &T::TypeInfo,
|
||||
iter: I,
|
||||
) -> Value {
|
||||
fn resolve_into_list<T, I>(executor: &Executor<T::Context>, info: &T::TypeInfo, iter: I) -> Value
|
||||
where
|
||||
I: Iterator<Item = T> + ExactSizeIterator,
|
||||
T: GraphQLType,
|
||||
{
|
||||
let stop_on_null = executor
|
||||
.current_type()
|
||||
.list_contents()
|
||||
.expect("Current type is not a list type")
|
||||
.is_non_null();
|
||||
|
||||
let mut result = Vec::new();
|
||||
let mut result = Vec::with_capacity(iter.len());
|
||||
|
||||
for o in iter {
|
||||
let value = executor.resolve_into_value(info, &o);
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
use indexmap::IndexMap;
|
||||
use std::hash::Hash;
|
||||
|
||||
use ast::{InputValue, ToInputValue};
|
||||
use parser::Spanning;
|
||||
use std::iter::FromIterator;
|
||||
use std::vec::IntoIter;
|
||||
|
||||
/// Serializable value returned from query and field execution.
|
||||
///
|
||||
|
@ -22,7 +21,152 @@ pub enum Value {
|
|||
String(String),
|
||||
Boolean(bool),
|
||||
List(Vec<Value>),
|
||||
Object(IndexMap<String, Value>),
|
||||
Object(Object),
|
||||
}
|
||||
|
||||
/// A Object value
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub struct Object {
|
||||
key_value_list: Vec<(String, Value)>,
|
||||
}
|
||||
|
||||
impl Object {
|
||||
/// Create a new Object value with a fixed number of
|
||||
/// preallocated slots for field-value pairs
|
||||
pub fn with_capacity(size: usize) -> Self {
|
||||
Object {
|
||||
key_value_list: Vec::with_capacity(size),
|
||||
}
|
||||
}
|
||||
|
||||
/// Add a new field with a value
|
||||
///
|
||||
/// If there is already a field with the same name the old value
|
||||
/// is returned
|
||||
pub fn add_field<K>(&mut self, k: K, value: Value) -> Option<Value>
|
||||
where
|
||||
K: Into<String>,
|
||||
for<'a> &'a str: PartialEq<K>,
|
||||
{
|
||||
if let Some(item) = self
|
||||
.key_value_list
|
||||
.iter_mut()
|
||||
.find(|&&mut (ref key, _)| (key as &str) == k)
|
||||
{
|
||||
return Some(::std::mem::replace(&mut item.1, value));
|
||||
}
|
||||
self.key_value_list.push((k.into(), value));
|
||||
None
|
||||
}
|
||||
|
||||
/// Check if the object already contains a field with the given name
|
||||
pub fn contains_field<K>(&self, f: K) -> bool
|
||||
where
|
||||
for<'a> &'a str: PartialEq<K>,
|
||||
{
|
||||
self.key_value_list
|
||||
.iter()
|
||||
.any(|&(ref key, _)| (key as &str) == f)
|
||||
}
|
||||
|
||||
/// Get a iterator over all field value pairs
|
||||
///
|
||||
/// This method returns a iterator over `&'a (String, Value)`
|
||||
// TODO: change this to `-> impl Iterator<Item = &(String, Value)>`
|
||||
// as soon as juniper bumps the minimal supported rust verion to 1.26
|
||||
pub fn iter(&self) -> FieldIter {
|
||||
FieldIter {
|
||||
inner: self.key_value_list.iter(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get a iterator over all mutable field value pairs
|
||||
///
|
||||
/// This method returns a iterator over `&mut 'a (String, Value)`
|
||||
// TODO: change this to `-> impl Iterator<Item = &mut (String, Value)>`
|
||||
// as soon as juniper bumps the minimal supported rust verion to 1.26
|
||||
pub fn iter_mut(&mut self) -> FieldIterMut {
|
||||
FieldIterMut {
|
||||
inner: self.key_value_list.iter_mut(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the current number of fields
|
||||
pub fn field_count(&self) -> usize {
|
||||
self.key_value_list.len()
|
||||
}
|
||||
|
||||
/// Get the value for a given field
|
||||
pub fn get_field_value<K>(&self, key: K) -> Option<&Value>
|
||||
where
|
||||
for<'a> &'a str: PartialEq<K>,
|
||||
{
|
||||
self.key_value_list
|
||||
.iter()
|
||||
.find(|&&(ref k, _)| (k as &str) == key)
|
||||
.map(|&(_, ref value)| value)
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoIterator for Object {
|
||||
type Item = (String, Value);
|
||||
type IntoIter = IntoIter<Self::Item>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
self.key_value_list.into_iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Object> for Value {
|
||||
fn from(o: Object) -> Self {
|
||||
Value::Object(o)
|
||||
}
|
||||
}
|
||||
|
||||
impl<K> FromIterator<(K, Value)> for Object
|
||||
where
|
||||
K: Into<String>,
|
||||
for<'a> &'a str: PartialEq<K>,
|
||||
{
|
||||
fn from_iter<I>(iter: I) -> Self
|
||||
where
|
||||
I: IntoIterator<Item = (K, Value)>,
|
||||
{
|
||||
let iter = iter.into_iter();
|
||||
let mut ret = Self {
|
||||
key_value_list: Vec::with_capacity(iter.size_hint().0),
|
||||
};
|
||||
for (k, v) in iter {
|
||||
ret.add_field(k, v);
|
||||
}
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub struct FieldIter<'a> {
|
||||
inner: ::std::slice::Iter<'a, (String, Value)>,
|
||||
}
|
||||
|
||||
impl<'a> Iterator for FieldIter<'a> {
|
||||
type Item = &'a (String, Value);
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.inner.next()
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub struct FieldIterMut<'a> {
|
||||
inner: ::std::slice::IterMut<'a, (String, Value)>,
|
||||
}
|
||||
|
||||
impl<'a> Iterator for FieldIterMut<'a> {
|
||||
type Item = &'a mut (String, Value);
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.inner.next()
|
||||
}
|
||||
}
|
||||
|
||||
impl Value {
|
||||
|
@ -59,11 +203,8 @@ impl Value {
|
|||
}
|
||||
|
||||
/// Construct an object value.
|
||||
pub fn object<K>(o: IndexMap<K, Value>) -> Value
|
||||
where
|
||||
K: Into<String> + Eq + Hash,
|
||||
{
|
||||
Value::Object(o.into_iter().map(|(k, v)| (k.into(), v)).collect())
|
||||
pub fn object(o: Object) -> Value {
|
||||
Value::Object(o)
|
||||
}
|
||||
|
||||
// DISCRIMINATORS
|
||||
|
@ -85,7 +226,7 @@ impl Value {
|
|||
}
|
||||
|
||||
/// View the underlying object value, if present.
|
||||
pub fn as_object_value(&self) -> Option<&IndexMap<String, Value>> {
|
||||
pub fn as_object_value(&self) -> Option<&Object> {
|
||||
match *self {
|
||||
Value::Object(ref o) => Some(o),
|
||||
_ => None,
|
||||
|
@ -93,7 +234,7 @@ impl Value {
|
|||
}
|
||||
|
||||
/// Mutable view into the underlying object value, if present.
|
||||
pub fn as_mut_object_value(&mut self) -> Option<&mut IndexMap<String, Value>> {
|
||||
pub fn as_mut_object_value(&mut self) -> Option<&mut Object> {
|
||||
match *self {
|
||||
Value::Object(ref mut o) => Some(o),
|
||||
_ => None,
|
||||
|
@ -132,7 +273,7 @@ impl ToInputValue for Value {
|
|||
),
|
||||
Value::Object(ref o) => InputValue::Object(
|
||||
o.iter()
|
||||
.map(|(k, v)| {
|
||||
.map(|&(ref k, ref v)| {
|
||||
(
|
||||
Spanning::unlocated(k.clone()),
|
||||
Spanning::unlocated(v.to_input_value()),
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#[cfg(test)]
|
||||
use fnv::FnvHashMap;
|
||||
#[cfg(test)]
|
||||
use indexmap::IndexMap;
|
||||
use juniper::Object;
|
||||
|
||||
#[cfg(test)]
|
||||
use juniper::{self, execute, EmptyMutation, GraphQLType, RootNode, Value, Variables};
|
||||
|
@ -235,8 +235,8 @@ fn check_descriptions(
|
|||
object_name
|
||||
);
|
||||
run_type_info_query(&doc, |(type_info, values)| {
|
||||
assert_eq!(type_info.get("name"), Some(&Value::string(object_name)));
|
||||
assert_eq!(type_info.get("description"), Some(object_description));
|
||||
assert_eq!(type_info.get_field_value("name"), Some(&Value::string(object_name)));
|
||||
assert_eq!(type_info.get_field_value("description"), Some(object_description));
|
||||
assert!(
|
||||
values.contains(&Value::object(
|
||||
vec![
|
||||
|
@ -252,7 +252,7 @@ fn check_descriptions(
|
|||
#[cfg(test)]
|
||||
fn run_type_info_query<F>(doc: &str, f: F)
|
||||
where
|
||||
F: Fn((&IndexMap<String, Value>, &Vec<Value>)) -> (),
|
||||
F: Fn((&Object, &Vec<Value>)) -> (),
|
||||
{
|
||||
let schema = RootNode::new(Query, EmptyMutation::<()>::new());
|
||||
|
||||
|
@ -266,13 +266,13 @@ where
|
|||
let type_info = result
|
||||
.as_object_value()
|
||||
.expect("Result is not an object")
|
||||
.get("__type")
|
||||
.get_field_value("__type")
|
||||
.expect("__type field missing")
|
||||
.as_object_value()
|
||||
.expect("__type field not an object value");
|
||||
|
||||
let fields = type_info
|
||||
.get("fields")
|
||||
.get_field_value("fields")
|
||||
.expect("fields field missing")
|
||||
.as_list_value()
|
||||
.expect("fields not a list");
|
||||
|
|
Loading…
Reference in a new issue