Add missing marker trait impls for container types (#847)

This commit is contained in:
Kai Ren 2021-01-15 19:31:50 +02:00 committed by GitHub
parent 516c720962
commit 4682fe2f4e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 299 additions and 58 deletions

View file

@ -1472,3 +1472,91 @@ mod full_featured_struct {
);
}
}
mod issue_845 {
use std::sync::Arc;
use super::*;
#[derive(GraphQLUnion)]
enum Character {
A(Box<Human>),
B(Arc<Droid>),
}
enum QueryRoot {
Human,
Droid,
}
#[graphql_object]
impl QueryRoot {
fn character(&self) -> Character {
match self {
Self::Human => Character::A(Box::new(Human {
id: "human-32".to_string(),
home_planet: "earth".to_string(),
})),
Self::Droid => Character::B(Arc::new(Droid {
id: "droid-99".to_string(),
primary_function: "run".to_string(),
})),
}
}
}
const DOC: &str = r#"{
character {
... on Human {
humanId: id
homePlanet
}
... on Droid {
droidId: id
primaryFunction
}
}
}"#;
#[tokio::test]
async fn resolves_human() {
let schema = schema(QueryRoot::Human);
assert_eq!(
execute(DOC, None, &schema, &Variables::new(), &()).await,
Ok((
graphql_value!({"character": {"humanId": "human-32", "homePlanet": "earth"}}),
vec![],
)),
);
}
#[tokio::test]
async fn resolves_droid() {
let schema = schema(QueryRoot::Droid);
assert_eq!(
execute(DOC, None, &schema, &Variables::new(), &()).await,
Ok((
graphql_value!({"character": {"droidId": "droid-99", "primaryFunction": "run"}}),
vec![],
)),
);
}
#[tokio::test]
async fn is_graphql_union() {
const DOC: &str = r#"{
__type(name: "Character") {
kind
}
}"#;
let schema = schema(QueryRoot::Human);
assert_eq!(
execute(DOC, None, &schema, &Variables::new(), &()).await,
Ok((graphql_value!({"__type": {"kind": "UNION"}}), vec![])),
);
}
}

View file

@ -5,6 +5,8 @@
//! traits are used. Encountering an error where one of these traits
//! is involved implies that the construct is not valid in GraphQL.
use std::sync::Arc;
use crate::{GraphQLType, ScalarValue};
/// Maker object for GraphQL objects.
@ -23,6 +25,39 @@ pub trait GraphQLObjectType<S: ScalarValue>: GraphQLType<S> {
fn mark() {}
}
impl<'a, S, T> GraphQLObjectType<S> for &T
where
T: GraphQLObjectType<S> + ?Sized,
S: ScalarValue,
{
#[inline]
fn mark() {
T::mark()
}
}
impl<S, T> GraphQLObjectType<S> for Box<T>
where
T: GraphQLObjectType<S> + ?Sized,
S: ScalarValue,
{
#[inline]
fn mark() {
T::mark()
}
}
impl<S, T> GraphQLObjectType<S> for Arc<T>
where
T: GraphQLObjectType<S> + ?Sized,
S: ScalarValue,
{
#[inline]
fn mark() {
T::mark()
}
}
/// Maker trait for [GraphQL interfaces][1].
///
/// This trait extends the [`GraphQLType`] and is only used to mark an [interface][1]. During
@ -47,6 +82,39 @@ pub trait GraphQLInterface<S: ScalarValue>: GraphQLType<S> {
fn mark() {}
}
impl<'a, S, T> GraphQLInterface<S> for &T
where
T: GraphQLInterface<S> + ?Sized,
S: ScalarValue,
{
#[inline]
fn mark() {
T::mark()
}
}
impl<S, T> GraphQLInterface<S> for Box<T>
where
T: GraphQLInterface<S> + ?Sized,
S: ScalarValue,
{
#[inline]
fn mark() {
T::mark()
}
}
impl<S, T> GraphQLInterface<S> for Arc<T>
where
T: GraphQLInterface<S> + ?Sized,
S: ScalarValue,
{
#[inline]
fn mark() {
T::mark()
}
}
/// Maker trait for [GraphQL unions][1].
///
/// This trait extends the [`GraphQLType`] and is only used to mark an [union][1]. During compile
@ -71,6 +139,39 @@ pub trait GraphQLUnion<S: ScalarValue>: GraphQLType<S> {
fn mark() {}
}
impl<'a, S, T> GraphQLUnion<S> for &T
where
T: GraphQLUnion<S> + ?Sized,
S: ScalarValue,
{
#[inline]
fn mark() {
T::mark()
}
}
impl<S, T> GraphQLUnion<S> for Box<T>
where
T: GraphQLUnion<S> + ?Sized,
S: ScalarValue,
{
#[inline]
fn mark() {
T::mark()
}
}
impl<S, T> GraphQLUnion<S> for Arc<T>
where
T: GraphQLUnion<S> + ?Sized,
S: ScalarValue,
{
#[inline]
fn mark() {
T::mark()
}
}
/// Marker trait for types which can be used as output types.
///
/// The GraphQL specification differentiates between input and output
@ -86,6 +187,74 @@ pub trait IsOutputType<S: ScalarValue> /*: GraphQLType<S>*/ {
fn mark() {}
}
impl<'a, S, T> IsOutputType<S> for &T
where
T: IsOutputType<S> + ?Sized,
S: ScalarValue,
{
#[inline]
fn mark() {
T::mark()
}
}
impl<S, T> IsOutputType<S> for Box<T>
where
T: IsOutputType<S> + ?Sized,
S: ScalarValue,
{
#[inline]
fn mark() {
T::mark()
}
}
impl<S, T> IsOutputType<S> for Arc<T>
where
T: IsOutputType<S> + ?Sized,
S: ScalarValue,
{
#[inline]
fn mark() {
T::mark()
}
}
impl<S, T> IsOutputType<S> for Option<T>
where
T: IsOutputType<S>,
S: ScalarValue,
{
#[inline]
fn mark() {
T::mark()
}
}
impl<S, T> IsOutputType<S> for Vec<T>
where
T: IsOutputType<S>,
S: ScalarValue,
{
#[inline]
fn mark() {
T::mark()
}
}
impl<S, T> IsOutputType<S> for [T]
where
T: IsOutputType<S>,
S: ScalarValue,
{
#[inline]
fn mark() {
T::mark()
}
}
impl<'a, S> IsOutputType<S> for str where S: ScalarValue {}
/// Marker trait for types which can be used as input types.
///
/// The GraphQL specification differentiates between input and output
@ -100,59 +269,15 @@ pub trait IsInputType<S: ScalarValue>: GraphQLType<S> {
fn mark() {}
}
impl<S, T> IsInputType<S> for Option<T>
where
T: IsInputType<S>,
S: ScalarValue,
{
}
impl<S, T> IsOutputType<S> for Option<T>
where
T: IsOutputType<S>,
S: ScalarValue,
{
}
impl<S, T> IsOutputType<S> for Vec<T>
where
T: IsOutputType<S>,
S: ScalarValue,
{
}
impl<S, T> IsOutputType<S> for [T]
where
T: IsOutputType<S>,
S: ScalarValue,
{
}
impl<S, T> IsInputType<S> for Vec<T>
where
T: IsInputType<S>,
S: ScalarValue,
{
}
impl<S, T> IsInputType<S> for [T]
where
T: IsInputType<S>,
S: ScalarValue,
{
}
impl<'a, S, T> IsInputType<S> for &T
where
T: IsInputType<S> + ?Sized,
S: ScalarValue,
{
}
impl<'a, S, T> IsOutputType<S> for &T
where
T: IsOutputType<S> + ?Sized,
S: ScalarValue,
{
#[inline]
fn mark() {
T::mark()
}
}
impl<S, T> IsInputType<S> for Box<T>
@ -160,26 +285,54 @@ where
T: IsInputType<S> + ?Sized,
S: ScalarValue,
{
}
impl<S, T> IsOutputType<S> for Box<T>
where
T: IsOutputType<S> + ?Sized,
S: ScalarValue,
{
#[inline]
fn mark() {
T::mark()
}
}
impl<S, T> IsInputType<S> for std::sync::Arc<T>
impl<S, T> IsInputType<S> for Arc<T>
where
T: IsInputType<S> + ?Sized,
S: ScalarValue,
{
#[inline]
fn mark() {
T::mark()
}
}
impl<S, T> IsOutputType<S> for std::sync::Arc<T>
impl<S, T> IsInputType<S> for Option<T>
where
T: IsOutputType<S> + ?Sized,
T: IsInputType<S>,
S: ScalarValue,
{
#[inline]
fn mark() {
T::mark()
}
}
impl<S, T> IsInputType<S> for Vec<T>
where
T: IsInputType<S>,
S: ScalarValue,
{
#[inline]
fn mark() {
T::mark()
}
}
impl<S, T> IsInputType<S> for [T]
where
T: IsInputType<S>,
S: ScalarValue,
{
#[inline]
fn mark() {
T::mark()
}
}
impl<'a, S> IsInputType<S> for str where S: ScalarValue {}
impl<'a, S> IsOutputType<S> for str where S: ScalarValue {}