Impl fields resolving, vol.2 [skip ci]

This commit is contained in:
tyranron 2022-08-29 20:19:24 +03:00
commit d1f2173109
No known key found for this signature in database
GPG key ID: 762E144FB230A4F0
33 changed files with 337 additions and 209 deletions
examples/warp_subscriptions
juniper
juniper_actix
juniper_codegen
Cargo.toml
src
graphql_enum
graphql_object
graphql_scalar
graphql_union
juniper_hyper
juniper_iron
juniper_rocket
juniper_subscriptions
juniper_warp
tests

View file

@ -8,7 +8,7 @@ publish = false
[dependencies] [dependencies]
async-stream = "0.3" async-stream = "0.3"
env_logger = "0.9" env_logger = "0.9"
futures = "0.3.1" futures = "0.3"
juniper = { path = "../../juniper" } juniper = { path = "../../juniper" }
juniper_graphql_ws = { path = "../../juniper_graphql_ws" } juniper_graphql_ws = { path = "../../juniper_graphql_ws" }
juniper_warp = { path = "../../juniper_warp", features = ["subscriptions"] } juniper_warp = { path = "../../juniper_warp", features = ["subscriptions"] }

View file

@ -40,10 +40,10 @@ anyhow = { version = "1.0.32", default-features = false, optional = true }
async-trait = "0.1.39" async-trait = "0.1.39"
bigdecimal = { version = "0.3", optional = true } bigdecimal = { version = "0.3", optional = true }
bson = { version = "2.4", features = ["chrono-0_4"], optional = true } bson = { version = "2.4", features = ["chrono-0_4"], optional = true }
chrono = { version = "0.4", features = ["alloc"], default-features = false, optional = true } chrono = { version = "0.4.20", features = ["alloc"], default-features = false, optional = true }
chrono-tz = { version = "0.6", default-features = false, optional = true } chrono-tz = { version = "0.6", default-features = false, optional = true }
fnv = "1.0.3" fnv = "1.0.3"
futures = { version = "0.3.1", features = ["alloc"], default-features = false } futures = { version = "0.3.22", features = ["alloc"], default-features = false }
futures-enum = { version = "0.1.12", default-features = false } futures-enum = { version = "0.1.12", default-features = false }
graphql-parser = { version = "0.4", optional = true } graphql-parser = { version = "0.4", optional = true }
indexmap = { version = "1.0", features = ["serde-1"] } indexmap = { version = "1.0", features = ["serde-1"] }
@ -62,7 +62,7 @@ getrandom = { version = "0.2", features = ["js"] }
[dev-dependencies] [dev-dependencies]
bencher = "0.1.2" bencher = "0.1.2"
chrono = { version = "0.4", features = ["alloc"], default-features = false } chrono = { version = "0.4.20", features = ["alloc"], default-features = false }
pretty_assertions = "1.0.0" pretty_assertions = "1.0.0"
serde_json = "1.0.2" serde_json = "1.0.2"
tokio = { version = "1.0", features = ["macros", "time", "rt-multi-thread"] } tokio = { version = "1.0", features = ["macros", "time", "rt-multi-thread"] }

View file

@ -96,9 +96,10 @@ mod interface {
mod union { mod union {
use crate::{ use crate::{
graphql_object, GraphQLUnion, graphql_value, graphql_object, graphql_value,
schema::model::RootNode, schema::model::RootNode,
types::scalars::{EmptyMutation, EmptySubscription}, types::scalars::{EmptyMutation, EmptySubscription},
GraphQLUnion,
}; };
#[derive(GraphQLUnion)] #[derive(GraphQLUnion)]

View file

@ -75,6 +75,7 @@ pub use crate::{
FromContext, IntoFieldError, IntoResolvable, LookAheadArgument, LookAheadMethods, FromContext, IntoFieldError, IntoResolvable, LookAheadArgument, LookAheadMethods,
LookAheadSelection, LookAheadValue, OwnedExecutor, Registry, ValuesStream, Variables, LookAheadSelection, LookAheadValue, OwnedExecutor, Registry, ValuesStream, Variables,
}, },
extract::Extract,
introspection::IntrospectionFormat, introspection::IntrospectionFormat,
macros::helper::subscription::{ExtractTypeFromStream, IntoFieldResult}, macros::helper::subscription::{ExtractTypeFromStream, IntoFieldResult},
parser::{ParseError, ScalarToken, Spanning}, parser::{ParseError, ScalarToken, Spanning},
@ -95,7 +96,6 @@ pub use crate::{
}, },
validation::RuleError, validation::RuleError,
value::{DefaultScalarValue, Object, ParseScalarResult, ParseScalarValue, ScalarValue, Value}, value::{DefaultScalarValue, Object, ParseScalarResult, ParseScalarValue, ScalarValue, Value},
extract::Extract,
}; };
/// An error that prevented query execution /// An error that prevented query execution

View file

@ -5,7 +5,6 @@ use crate::{
reflect, Arguments, BoxFuture, ExecutionResult, Executor, FieldResult, IntoFieldError, reflect, Arguments, BoxFuture, ExecutionResult, Executor, FieldResult, IntoFieldError,
Registry, Selection, Registry, Selection,
}; };
use juniper::resolve;
pub trait Type<TypeInfo: ?Sized, ScalarValue, Behavior: ?Sized = behavior::Standard> { pub trait Type<TypeInfo: ?Sized, ScalarValue, Behavior: ?Sized = behavior::Standard> {
fn meta<'r, 'ti: 'r>( fn meta<'r, 'ti: 'r>(
@ -54,6 +53,12 @@ pub trait ValueAsync<
) -> BoxFuture<'r, ExecutionResult<ScalarValue>>; ) -> BoxFuture<'r, ExecutionResult<ScalarValue>>;
} }
pub trait Resolvable<ScalarValue, Behavior: ?Sized = behavior::Standard> {
type Value;
fn into_value(self) -> FieldResult<Self::Value, ScalarValue>;
}
pub trait ConcreteValue< pub trait ConcreteValue<
TypeInfo: ?Sized, TypeInfo: ?Sized,
Context: ?Sized, Context: ?Sized,
@ -204,75 +209,3 @@ pub trait InputValueAsRef<ScalarValue, Behavior: ?Sized = behavior::Standard> {
pub trait ScalarToken<ScalarValue, Behavior: ?Sized = behavior::Standard> { pub trait ScalarToken<ScalarValue, Behavior: ?Sized = behavior::Standard> {
fn parse_scalar_token(token: parser::ScalarToken<'_>) -> Result<ScalarValue, ParseError>; fn parse_scalar_token(token: parser::ScalarToken<'_>) -> Result<ScalarValue, ParseError>;
} }
/*
pub trait IntoResolvable<
ScalarValue,
>
{
type Type;
fn into_resolvable(self) -> FieldResult<Self::Type, ScalarValue>;
}
impl<T, SV> IntoResolvable<SV> for T
where
T: crate::GraphQLValue<SV>,
SV: crate::ScalarValue,
{
type Type = Self;
fn into_resolvable(self) -> FieldResult<Self, SV> {
Ok(self)
}
}
impl<T, E, SV> IntoResolvable<SV> for Result<T, E>
where
T: crate::GraphQLValue<SV>,
SV: crate::ScalarValue,
E: IntoFieldError<SV>,
{
type Type = T;
fn into_resolvable(self) -> FieldResult<Self::Type, SV> {
self.map_err(IntoFieldError::into_field_error)
}
}
*/
#[doc(hidden)]
pub trait IntoResolvable<S, T>
where
T: crate::GraphQLValue<S>,
S: crate::ScalarValue,
{
type Type;
#[doc(hidden)]
fn into_resolvable(self) -> FieldResult<T, S>;
}
impl<'a, S, T> IntoResolvable<S, T> for T
where
T: crate::GraphQLValue<S>,
S: crate::ScalarValue,
{
type Type = T;
fn into_resolvable(self) -> FieldResult<T, S> {
Ok(self)
}
}
impl<'a, S, T, E: IntoFieldError<S>> IntoResolvable<S, T> for Result<T, E>
where
S: crate::ScalarValue,
T: crate::GraphQLValue<S>,
{
type Type = T;
fn into_resolvable(self) -> FieldResult<T, S> {
self.map_err(IntoFieldError::into_field_error)
}
}

View file

@ -6,7 +6,8 @@ use crate::{
graphql, graphql,
meta::MetaType, meta::MetaType,
parser::{ParseError, ScalarToken}, parser::{ParseError, ScalarToken},
reflect, resolve, Arguments, BoxFuture, ExecutionResult, Executor, Registry, Selection, reflect, resolve, Arguments, BoxFuture, ExecutionResult, Executor, FieldResult, Registry,
Selection,
}; };
impl<T, TI, SV, BH> resolve::Type<TI, SV, BH> for Arc<T> impl<T, TI, SV, BH> resolve::Type<TI, SV, BH> for Arc<T>
@ -79,6 +80,18 @@ where
} }
} }
impl<T, SV, BH> resolve::Resolvable<SV, BH> for Arc<T>
where
T: ?Sized,
BH: ?Sized,
{
type Value = Self;
fn into_value(self) -> FieldResult<Self, SV> {
Ok(self)
}
}
impl<T, TI, CX, SV, BH> resolve::ConcreteValue<TI, CX, SV, BH> for Arc<T> impl<T, TI, CX, SV, BH> resolve::ConcreteValue<TI, CX, SV, BH> for Arc<T>
where where
T: resolve::ConcreteValue<TI, CX, SV, BH> + ?Sized, T: resolve::ConcreteValue<TI, CX, SV, BH> + ?Sized,

View file

@ -12,7 +12,7 @@ use crate::{
executor::{ExecutionResult, Executor, Registry}, executor::{ExecutionResult, Executor, Registry},
graphql, reflect, resolve, graphql, reflect, resolve,
schema::meta::MetaType, schema::meta::MetaType,
BoxFuture, FieldError, IntoFieldError, Selection, BoxFuture, FieldError, FieldResult, IntoFieldError, Selection,
}; };
use super::iter; use super::iter;
@ -71,6 +71,17 @@ where
} }
} }
impl<T, SV, BH, const N: usize> resolve::Resolvable<SV, BH> for [T; N]
where
BH: ?Sized,
{
type Value = Self;
fn into_value(self) -> FieldResult<Self, SV> {
Ok(self)
}
}
impl<T, SV, BH, const N: usize> resolve::ToInputValue<SV, BH> for [T; N] impl<T, SV, BH, const N: usize> resolve::ToInputValue<SV, BH> for [T; N]
where where
T: resolve::ToInputValue<SV, BH>, T: resolve::ToInputValue<SV, BH>,

View file

@ -1,3 +1,5 @@
use std::future;
use crate::{ use crate::{
ast::Selection, ast::Selection,
executor::{ExecutionResult, Executor}, executor::{ExecutionResult, Executor},
@ -254,7 +256,7 @@ where
let is_non_null = meta_field.field_type.is_non_null(); let is_non_null = meta_field.field_type.is_non_null();
let response_name = response_name.to_string(); let response_name = response_name.to_string();
async_values.push(AsyncValueFuture::Field(async move { async_values.push_back(AsyncValueFuture::Field(async move {
// TODO: implement custom future type instead of // TODO: implement custom future type instead of
// two-level boxing. // two-level boxing.
let res = instance let res = instance
@ -317,12 +319,12 @@ where
if let Ok(Value::Object(obj)) = sub_result { if let Ok(Value::Object(obj)) = sub_result {
for (k, v) in obj { for (k, v) in obj {
async_values.push(AsyncValueFuture::FragmentSpread(async move { async_values.push_back(AsyncValueFuture::FragmentSpread(
AsyncValue::Field(AsyncField { future::ready(AsyncValue::Field(AsyncField {
name: k, name: k,
value: Some(v), value: Some(v),
}) })),
})); ));
} }
} else if let Err(e) = sub_result { } else if let Err(e) = sub_result {
sub_exec.push_error_at(e, *start_pos); sub_exec.push_error_at(e, *start_pos);
@ -362,19 +364,19 @@ where
if let Ok(Value::Object(obj)) = sub_result { if let Ok(Value::Object(obj)) = sub_result {
for (k, v) in obj { for (k, v) in obj {
async_values.push(AsyncValueFuture::InlineFragment1(async move { async_values.push_back(AsyncValueFuture::InlineFragment1(
AsyncValue::Field(AsyncField { future::ready(AsyncValue::Field(AsyncField {
name: k, name: k,
value: Some(v), value: Some(v),
}) })),
})); ));
} }
} else if let Err(e) = sub_result { } else if let Err(e) = sub_result {
sub_exec.push_error_at(e, *start_pos); sub_exec.push_error_at(e, *start_pos);
} }
} }
} else { } else {
async_values.push(AsyncValueFuture::InlineFragment2(async move { async_values.push_back(AsyncValueFuture::InlineFragment2(async move {
let value = resolve_selection_set_into_async( let value = resolve_selection_set_into_async(
instance, instance,
info, info,

View file

@ -4,7 +4,8 @@ use crate::{
graphql, graphql,
meta::MetaType, meta::MetaType,
parser::{ParseError, ScalarToken}, parser::{ParseError, ScalarToken},
reflect, resolve, Arguments, BoxFuture, ExecutionResult, Executor, Registry, Selection, reflect, resolve, Arguments, BoxFuture, ExecutionResult, Executor, FieldResult, Registry,
Selection,
}; };
impl<T, TI, SV, BH> resolve::Type<TI, SV, BH> for Box<T> impl<T, TI, SV, BH> resolve::Type<TI, SV, BH> for Box<T>
@ -77,6 +78,18 @@ where
} }
} }
impl<T, SV, BH> resolve::Resolvable<SV, BH> for Box<T>
where
T: ?Sized,
BH: ?Sized,
{
type Value = Self;
fn into_value(self) -> FieldResult<Self, SV> {
Ok(self)
}
}
impl<T, TI, CX, SV, BH> resolve::ConcreteValue<TI, CX, SV, BH> for Box<T> impl<T, TI, CX, SV, BH> resolve::ConcreteValue<TI, CX, SV, BH> for Box<T>
where where
T: resolve::ConcreteValue<TI, CX, SV, BH> + ?Sized, T: resolve::ConcreteValue<TI, CX, SV, BH> + ?Sized,

View file

@ -6,7 +6,8 @@ use crate::{
graphql, graphql,
meta::MetaType, meta::MetaType,
parser::{ParseError, ScalarToken}, parser::{ParseError, ScalarToken},
reflect, resolve, Arguments, BoxFuture, ExecutionResult, Executor, Registry, Selection, reflect, resolve, Arguments, BoxFuture, ExecutionResult, Executor, FieldResult, Registry,
Selection,
}; };
impl<'me, T, TI, SV, BH> resolve::Type<TI, SV, BH> for Cow<'me, T> impl<'me, T, TI, SV, BH> resolve::Type<TI, SV, BH> for Cow<'me, T>
@ -84,6 +85,18 @@ where
} }
} }
impl<'me, T, SV, BH> resolve::Resolvable<SV, BH> for Cow<'me, T>
where
T: ToOwned + ?Sized + 'me,
BH: ?Sized,
{
type Value = Self;
fn into_value(self) -> FieldResult<Self, SV> {
Ok(self)
}
}
impl<'me, T, TI, CX, SV, BH> resolve::ConcreteValue<TI, CX, SV, BH> for Cow<'me, T> impl<'me, T, TI, CX, SV, BH> resolve::ConcreteValue<TI, CX, SV, BH> for Cow<'me, T>
where where
T: resolve::ConcreteValue<TI, CX, SV, BH> + ToOwned + ?Sized + 'me, T: resolve::ConcreteValue<TI, CX, SV, BH> + ToOwned + ?Sized + 'me,

View file

@ -15,7 +15,7 @@ use crate::{
base::{GraphQLType, GraphQLValue}, base::{GraphQLType, GraphQLValue},
marker::IsInputType, marker::IsInputType,
}, },
BoxFuture, ScalarValue, Selection, BoxFuture, FieldResult, ScalarValue, Selection,
}; };
/// [`Nullable`] wrapper allowing to distinguish between an implicit and /// [`Nullable`] wrapper allowing to distinguish between an implicit and
@ -330,6 +330,17 @@ where
} }
} }
impl<T, SV, BH> resolve::Resolvable<SV, BH> for Nullable<T>
where
BH: ?Sized,
{
type Value = Self;
fn into_value(self) -> FieldResult<Self, SV> {
Ok(self)
}
}
impl<T, SV, BH> resolve::ToInputValue<SV, BH> for Nullable<T> impl<T, SV, BH> resolve::ToInputValue<SV, BH> for Nullable<T>
where where
T: resolve::ToInputValue<SV, BH>, T: resolve::ToInputValue<SV, BH>,

View file

@ -7,7 +7,7 @@ use crate::{
executor::{ExecutionResult, Executor, Registry}, executor::{ExecutionResult, Executor, Registry},
graphql, reflect, resolve, graphql, reflect, resolve,
schema::meta::MetaType, schema::meta::MetaType,
BoxFuture, Selection, BoxFuture, FieldResult, Selection,
}; };
impl<T, TI, SV, BH> resolve::Type<TI, SV, BH> for Option<T> impl<T, TI, SV, BH> resolve::Type<TI, SV, BH> for Option<T>
@ -65,6 +65,17 @@ where
} }
} }
impl<T, SV, BH> resolve::Resolvable<SV, BH> for Option<T>
where
BH: ?Sized,
{
type Value = Self;
fn into_value(self) -> FieldResult<Self, SV> {
Ok(self)
}
}
impl<T, SV, BH> resolve::ToInputValue<SV, BH> for Option<T> impl<T, SV, BH> resolve::ToInputValue<SV, BH> for Option<T>
where where
T: resolve::ToInputValue<SV, BH>, T: resolve::ToInputValue<SV, BH>,

View file

@ -6,7 +6,8 @@ use crate::{
graphql, graphql,
meta::MetaType, meta::MetaType,
parser::{ParseError, ScalarToken}, parser::{ParseError, ScalarToken},
reflect, resolve, Arguments, BoxFuture, ExecutionResult, Executor, Registry, Selection, reflect, resolve, Arguments, BoxFuture, ExecutionResult, Executor, FieldResult, Registry,
Selection,
}; };
impl<T, TI, SV, BH> resolve::Type<TI, SV, BH> for Rc<T> impl<T, TI, SV, BH> resolve::Type<TI, SV, BH> for Rc<T>
@ -79,6 +80,18 @@ where
} }
} }
impl<T, SV, BH> resolve::Resolvable<SV, BH> for Rc<T>
where
T: ?Sized,
BH: ?Sized,
{
type Value = Self;
fn into_value(self) -> FieldResult<Self, SV> {
Ok(self)
}
}
impl<T, TI, CX, SV, BH> resolve::ConcreteValue<TI, CX, SV, BH> for Rc<T> impl<T, TI, CX, SV, BH> resolve::ConcreteValue<TI, CX, SV, BH> for Rc<T>
where where
T: resolve::ConcreteValue<TI, CX, SV, BH> + ?Sized, T: resolve::ConcreteValue<TI, CX, SV, BH> + ?Sized,

View file

@ -6,7 +6,8 @@ use crate::{
graphql, graphql,
meta::MetaType, meta::MetaType,
parser::{ParseError, ScalarToken}, parser::{ParseError, ScalarToken},
reflect, resolve, Arguments, BoxFuture, ExecutionResult, Executor, Registry, Selection, reflect, resolve, Arguments, BoxFuture, ExecutionResult, Executor, FieldResult, Registry,
Selection,
}; };
impl<'me, T, TI, SV, BH> resolve::Type<TI, SV, BH> for &'me T impl<'me, T, TI, SV, BH> resolve::Type<TI, SV, BH> for &'me T
@ -79,6 +80,18 @@ where
} }
} }
impl<'me, T, SV, BH> resolve::Resolvable<SV, BH> for &'me T
where
T: ?Sized,
BH: ?Sized,
{
type Value = Self;
fn into_value(self) -> FieldResult<Self, SV> {
Ok(self)
}
}
impl<'me, T, TI, CX, SV, BH> resolve::ConcreteValue<TI, CX, SV, BH> for &'me T impl<'me, T, TI, CX, SV, BH> resolve::ConcreteValue<TI, CX, SV, BH> for &'me T
where where
T: resolve::ConcreteValue<TI, CX, SV, BH> + ?Sized, T: resolve::ConcreteValue<TI, CX, SV, BH> + ?Sized,

View file

@ -6,7 +6,8 @@ use crate::{
graphql, graphql,
meta::MetaType, meta::MetaType,
parser::{ParseError, ScalarToken}, parser::{ParseError, ScalarToken},
reflect, resolve, Arguments, BoxFuture, ExecutionResult, Executor, Registry, Selection, reflect, resolve, Arguments, BoxFuture, ExecutionResult, Executor, FieldResult, Registry,
Selection,
}; };
impl<'me, T, TI, SV, BH> resolve::Type<TI, SV, BH> for &'me mut T impl<'me, T, TI, SV, BH> resolve::Type<TI, SV, BH> for &'me mut T
@ -79,6 +80,18 @@ where
} }
} }
impl<'me, T, SV, BH> resolve::Resolvable<SV, BH> for &'me mut T
where
T: ?Sized,
BH: ?Sized,
{
type Value = Self;
fn into_value(self) -> FieldResult<Self, SV> {
Ok(self)
}
}
impl<'me, T, TI, CX, SV, BH> resolve::ConcreteValue<TI, CX, SV, BH> for &'me mut T impl<'me, T, TI, CX, SV, BH> resolve::ConcreteValue<TI, CX, SV, BH> for &'me mut T
where where
T: resolve::ConcreteValue<TI, CX, SV, BH> + ?Sized, T: resolve::ConcreteValue<TI, CX, SV, BH> + ?Sized,

View file

@ -1,6 +1,18 @@
//! GraphQL implementation for [`Result`]. //! GraphQL implementation for [`Result`].
use crate::reflect; use crate::{reflect, resolve, FieldResult, IntoFieldError};
impl<T, E, SV, BH> resolve::Resolvable<SV, BH> for Result<T, E>
where
E: IntoFieldError<SV>,
BH: ?Sized,
{
type Value = T;
fn into_value(self) -> FieldResult<Self::Value, SV> {
self.map_err(IntoFieldError::into_field_error)
}
}
impl<T, E, BH> reflect::BaseType<BH> for Result<T, E> impl<T, E, BH> reflect::BaseType<BH> for Result<T, E>
where where

View file

@ -5,7 +5,7 @@ use crate::{
executor::{ExecutionResult, Executor, Registry}, executor::{ExecutionResult, Executor, Registry},
graphql, reflect, resolve, graphql, reflect, resolve,
schema::meta::MetaType, schema::meta::MetaType,
BoxFuture, FieldError, IntoFieldError, Selection, BoxFuture, FieldError, FieldResult, IntoFieldError, Selection,
}; };
use super::iter; use super::iter;
@ -64,6 +64,17 @@ where
} }
} }
impl<T, SV, BH> resolve::Resolvable<SV, BH> for Vec<T>
where
BH: ?Sized,
{
type Value = Self;
fn into_value(self) -> FieldResult<Self, SV> {
Ok(self)
}
}
impl<T, SV, BH> resolve::ToInputValue<SV, BH> for Vec<T> impl<T, SV, BH> resolve::ToInputValue<SV, BH> for Vec<T>
where where
T: resolve::ToInputValue<SV, BH>, T: resolve::ToInputValue<SV, BH>,

View file

@ -27,7 +27,7 @@ actix-http = "3.0"
actix-web = "4.0" actix-web = "4.0"
actix-web-actors = "4.1.0" actix-web-actors = "4.1.0"
anyhow = "1.0" anyhow = "1.0"
futures = "0.3" futures = "0.3.22"
juniper = { version = "0.16.0-dev", path = "../juniper", default-features = false } juniper = { version = "0.16.0-dev", path = "../juniper", default-features = false }
juniper_graphql_ws = { version = "0.4.0-dev", path = "../juniper_graphql_ws", optional = true } juniper_graphql_ws = { version = "0.4.0-dev", path = "../juniper_graphql_ws", optional = true }
http = "0.2.4" http = "0.2.4"

View file

@ -30,6 +30,6 @@ url = "2.0"
[dev-dependencies] [dev-dependencies]
derive_more = "0.99.7" derive_more = "0.99.7"
futures = "0.3" futures = "0.3.22"
juniper = { path = "../juniper" } juniper = { path = "../juniper" }
serde = "1.0" serde = "1.0"

View file

@ -417,6 +417,7 @@ impl ToTokens for Definition {
self.impl_resolve_type_name().to_tokens(into); self.impl_resolve_type_name().to_tokens(into);
self.impl_resolve_value().to_tokens(into); self.impl_resolve_value().to_tokens(into);
self.impl_resolve_value_async().to_tokens(into); self.impl_resolve_value_async().to_tokens(into);
self.impl_resolvable().to_tokens(into);
self.impl_resolve_to_input_value().to_tokens(into); self.impl_resolve_to_input_value().to_tokens(into);
self.impl_resolve_input_value().to_tokens(into); self.impl_resolve_input_value().to_tokens(into);
self.impl_graphql_input_type().to_tokens(into); self.impl_graphql_input_type().to_tokens(into);
@ -868,6 +869,31 @@ impl Definition {
} }
} }
/// Returns generated code implementing [`resolve::Resolvable`] trait for
/// this [GraphQL enum][0].
///
/// [`resolve::Resolvable`]: juniper::resolve::Resolvable
/// [0]: https://spec.graphql.org/October2021#sec-Enums
fn impl_resolvable(&self) -> TokenStream {
let bh = &self.behavior;
let (ty, generics) = self.ty_and_generics();
let (sv, generics) = self.mix_scalar_value(generics);
let (impl_gens, _, where_clause) = generics.split_for_impl();
quote! {
#[automatically_derived]
impl #impl_gens ::juniper::resolve::Resolvable<#sv, #bh>
for #ty #where_clause
{
type Value = Self;
fn into_value(self) -> ::juniper::FieldResult<Self, #sv> {
::juniper::FieldResult::Ok(self)
}
}
}
}
/// Returns generated code implementing [`FromInputValue`] trait for this /// Returns generated code implementing [`FromInputValue`] trait for this
/// [GraphQL enum][0]. /// [GraphQL enum][0].
/// ///

View file

@ -599,108 +599,108 @@ impl<Operation: ?Sized + 'static> Definition<Operation> {
}) })
.collect() .collect()
} }
/* /*
/// Returns generated code implementing [`resolve::StaticField`] trait for /// Returns generated code implementing [`resolve::StaticField`] trait for
/// each [field][1] of this [GraphQL object][0]. /// each [field][1] of this [GraphQL object][0].
/// ///
/// [`resolve::StaticField`]: juniper::resolve::StaticField /// [`resolve::StaticField`]: juniper::resolve::StaticField
/// [0]: https://spec.graphql.org/October2021#sec-Objects /// [0]: https://spec.graphql.org/October2021#sec-Objects
/// [1]: https://spec.graphql.org/October2021#sec-Language.Fields /// [1]: https://spec.graphql.org/October2021#sec-Language.Fields
#[must_use] #[must_use]
pub(crate) fn impl_resolve_static_field(&self) -> TokenStream { pub(crate) fn impl_resolve_static_field(&self) -> TokenStream {
let bh = &self.behavior; let bh = &self.behavior;
let (ty, generics) = self.ty_and_generics(); let (ty, generics) = self.ty_and_generics();
let (inf, generics) = self.mix_type_info(generics); let (inf, generics) = self.mix_type_info(generics);
let (cx, generics) = self.mix_context(generics); let (cx, generics) = self.mix_context(generics);
let (sv, generics) = self.mix_scalar_value(generics); let (sv, generics) = self.mix_scalar_value(generics);
self.fields self.fields
.iter() .iter()
.map(|field| { .map(|field| {
let mut generics = generics.clone(); let mut generics = generics.clone();
let (f_name, f_bh) = (&field.name, &field.behavior); let (f_name, f_bh) = (&field.name, &field.behavior);
let (f_ident, f_ty) = (&field.ident, &field.ty); let (f_ident, f_ty) = (&field.ident, &field.ty);
let body = if !field.is_async { let body = if !field.is_async {
generics.make_where_clause().predicates.push(parse_quote! { generics.make_where_clause().predicates.push(parse_quote! {
#f_ty: ::juniper::resolve::Value<#inf, #cx, #sv, #f_bh> #f_ty: ::juniper::resolve::Value<#inf, #cx, #sv, #f_bh>
}); });
let res = if field.is_method() { let res = if field.is_method() {
let args = field.arguments.as_ref().unwrap().iter().map(|arg| { let args = field.arguments.as_ref().unwrap().iter().map(|arg| {
match arg { match arg {
field::MethodArgument::Regular(arg) => { field::MethodArgument::Regular(arg) => {
let (a_ty, a_bh) = (&arg.ty, &arg.behavior); let (a_ty, a_bh) = (&arg.ty, &arg.behavior);
generics.make_where_clause().predicates.push(parse_quote! { generics.make_where_clause().predicates.push(parse_quote! {
#a_ty: ::juniper::resolve::InputValueOwned<#sv, #a_bh> #a_ty: ::juniper::resolve::InputValueOwned<#sv, #a_bh>
}); });
quote! { quote! {
args.resolve::<#a_ty, #a_bh>(#name)? args.resolve::<#a_ty, #a_bh>(#name)?
} }
} }
field::MethodArgument::Context(cx_ty) => { field::MethodArgument::Context(cx_ty) => {
generics.make_where_clause().predicates.push(parse_quote! { generics.make_where_clause().predicates.push(parse_quote! {
#cx: ::juniper::Extract<#cx_ty> #cx: ::juniper::Extract<#cx_ty>
}); });
quote! { quote! {
<#cx as ::juniper::Extract<#cx_ty>> <#cx as ::juniper::Extract<#cx_ty>>
::extract(executor.context()) ::extract(executor.context())
} }
} }
field::MethodArgument::Executor => { field::MethodArgument::Executor => {
quote! { quote! {
executor executor
}
} }
} }
});
let rcv = field.has_receiver.then(|| {
quote! { self, }
});
quote! { Self::#ident(#rcv #( #args ),*) }
} else {
quote! {
&self.#f_ident
} }
}); };
let rcv = field.has_receiver.then(|| { quote! {
quote! { self, } executor.resolve_value::<#f_bh, _, _>(#res, type_info)
}); }
quote! { Self::#ident(#rcv #( #args ),*) }
} else { } else {
quote! { quote! {
&self.#f_ident ::std::panic!(
"Tried to resolve async field `{}` on type `{}` with a sync resolver",
#f_name,
<Self as ::juniper::reflect::BaseType<#bh>>::NAME,
);
} }
}; };
quote! { let (impl_gens, _, where_clause) = generics.split_for_impl();
executor.resolve_value::<#f_bh, _, _>(#res, type_info)
}
} else {
quote! {
::std::panic!(
"Tried to resolve async field `{}` on type `{}` with a sync resolver",
#f_name,
<Self as ::juniper::reflect::BaseType<#bh>>::NAME,
);
}
};
let (impl_gens, _, where_clause) = generics.split_for_impl(); quote! {
#[automatically_derived]
quote! { impl #impl_gens ::juniper::resolve::StaticField<
#[automatically_derived] { ::juniper::reflect::fnv1a128(#f_name) },
impl #impl_gens ::juniper::resolve::StaticField< #inf, #cx, #sv, #bh,
{ ::juniper::reflect::fnv1a128(#f_name) }, > for #ty #where_clause {
#inf, #cx, #sv, #bh, fn resolve_static_field(
> for #ty #where_clause { &self,
fn resolve_static_field( args: &::juniper::Arguments<'_, #sv>,
&self, type_info: &#inf,
args: &::juniper::Arguments<'_, #sv>, executor: &::juniper::Executor<'_, '_, #cx, #sv>,
type_info: &#inf, ) -> ::juniper::ExecutionResult<#sv> {
executor: &::juniper::Executor<'_, '_, #cx, #sv>, #body
) -> ::juniper::ExecutionResult<#sv> { }
#body
} }
} }
} })
}) .collect()
.collect() }
} */
*/
/// Returns generated code implementing [`GraphQLType`] trait for this /// Returns generated code implementing [`GraphQLType`] trait for this
/// [GraphQL object][1]. /// [GraphQL object][1].
/// ///

View file

@ -351,6 +351,7 @@ impl ToTokens for Definition {
self.impl_resolve_type_name().to_tokens(into); self.impl_resolve_type_name().to_tokens(into);
self.impl_resolve_value().to_tokens(into); self.impl_resolve_value().to_tokens(into);
self.impl_resolve_value_async().to_tokens(into); self.impl_resolve_value_async().to_tokens(into);
self.impl_resolvable().to_tokens(into);
self.impl_resolve_to_input_value().to_tokens(into); self.impl_resolve_to_input_value().to_tokens(into);
self.impl_resolve_input_value().to_tokens(into); self.impl_resolve_input_value().to_tokens(into);
self.impl_resolve_scalar_token().to_tokens(into); self.impl_resolve_scalar_token().to_tokens(into);
@ -738,6 +739,31 @@ impl Definition {
} }
} }
/// Returns generated code implementing [`resolve::Resolvable`] trait for
/// this [GraphQL scalar][0].
///
/// [`resolve::Resolvable`]: juniper::resolve::Resolvable
/// [0]: https://spec.graphql.org/October2021#sec-Scalars
fn impl_resolvable(&self) -> TokenStream {
let bh = &self.behavior;
let (ty, generics) = self.ty_and_generics();
let (sv, generics) = self.mix_scalar_value(generics);
let (impl_gens, _, where_clause) = generics.split_for_impl();
quote! {
#[automatically_derived]
impl #impl_gens ::juniper::resolve::Resolvable<#sv, #bh>
for #ty #where_clause
{
type Value = Self;
fn into_value(self) -> ::juniper::FieldResult<Self, #sv> {
::juniper::FieldResult::Ok(self)
}
}
}
}
/// Returns generated code implementing [`InputValue`] trait for this /// Returns generated code implementing [`InputValue`] trait for this
/// [GraphQL scalar][1]. /// [GraphQL scalar][1].
/// ///

View file

@ -18,7 +18,7 @@ use syn::{
}; };
use crate::common::{ use crate::common::{
filter_attrs, gen, behavior, behavior, filter_attrs, gen,
parse::{ parse::{
attr::{err, OptionExt as _}, attr::{err, OptionExt as _},
ParseBufferExt as _, ParseBufferExt as _,

View file

@ -15,7 +15,7 @@ keywords = ["apollo", "graphql", "hyper", "juniper"]
exclude = ["/examples/", "/release.toml"] exclude = ["/examples/", "/release.toml"]
[dependencies] [dependencies]
futures = "0.3.1" futures = "0.3.22"
hyper = { version = "0.14", features = ["server", "runtime"] } hyper = { version = "0.14", features = ["server", "runtime"] }
juniper = { version = "0.16.0-dev", path = "../juniper", default-features = false } juniper = { version = "0.16.0-dev", path = "../juniper", default-features = false }
serde_json = "1.0" serde_json = "1.0"

View file

@ -18,7 +18,7 @@ keywords = ["apollo", "graphql", "iron", "juniper"]
exclude = ["/examples/", "/release.toml"] exclude = ["/examples/", "/release.toml"]
[dependencies] [dependencies]
futures = "0.3.1" futures = "0.3.22"
iron = ">= 0.5, < 0.7" iron = ">= 0.5, < 0.7"
juniper = { version = "0.16.0-dev", path = "../juniper", default-features = false } juniper = { version = "0.16.0-dev", path = "../juniper", default-features = false }
serde_json = "1.0.2" serde_json = "1.0.2"

View file

@ -18,7 +18,7 @@ keywords = ["apollo", "graphql", "juniper", "rocket"]
exclude = ["/examples/", "/tests/", "/release.toml"] exclude = ["/examples/", "/tests/", "/release.toml"]
[dependencies] [dependencies]
futures = "0.3.1" futures = "0.3.22"
juniper = { version = "0.16.0-dev", path = "../juniper", default-features = false } juniper = { version = "0.16.0-dev", path = "../juniper", default-features = false }
rocket = { version = "=0.5.0-rc.2", default-features = false } rocket = { version = "=0.5.0-rc.2", default-features = false }
serde_json = "1.0.2" serde_json = "1.0.2"

View file

@ -15,7 +15,7 @@ keywords = ["graphql", "server", "subscription", "web", "websocket"]
exclude = ["/release.toml"] exclude = ["/release.toml"]
[dependencies] [dependencies]
futures = "0.3.1" futures = "0.3.22"
juniper = { version = "0.16.0-dev", path = "../juniper", default-features = false } juniper = { version = "0.16.0-dev", path = "../juniper", default-features = false }
[dev-dependencies] [dev-dependencies]

View file

@ -23,7 +23,7 @@ subscriptions = ["juniper_graphql_ws"]
[dependencies] [dependencies]
anyhow = "1.0" anyhow = "1.0"
futures = "0.3.1" futures = "0.3.22"
juniper = { version = "0.16.0-dev", path = "../juniper", default-features = false } juniper = { version = "0.16.0-dev", path = "../juniper", default-features = false }
juniper_graphql_ws = { version = "0.4.0-dev", path = "../juniper_graphql_ws", optional = true } juniper_graphql_ws = { version = "0.4.0-dev", path = "../juniper_graphql_ws", optional = true }
serde = { version = "1.0.75", features = ["derive"] } serde = { version = "1.0.75", features = ["derive"] }

View file

@ -8,7 +8,7 @@ publish = false
rustversion = "1.0" rustversion = "1.0"
[dev-dependencies] [dev-dependencies]
futures = "0.3.1" futures = "0.3"
juniper = { path = "../../juniper" } juniper = { path = "../../juniper" }
serde_json = "1.0" serde_json = "1.0"
tokio = { version = "1.0", features = ["rt", "time", "macros"] } tokio = { version = "1.0", features = ["rt", "time", "macros"] }

View file

@ -1,8 +1,11 @@
error[E0277]: the trait bound `[bool; 2]: From<[bool; 3]>` is not satisfied error[E0277]: the trait bound `[bool; 2]: From<[bool; 3]>` is not satisfied
--> fail/interface/trait/argument_wrong_default_array.rs:3:1 --> fail/interface/trait/argument_wrong_default_array.rs:5:41
| |
3 | #[graphql_interface] 3 | #[graphql_interface]
| ^^^^^^^^^^^^^^^^^^^^ the trait `From<[bool; 3]>` is not implemented for `[bool; 2]` | -------------------- required by a bound introduced by this call
4 | trait Character {
5 | fn wrong(&self, #[graphql(default = [true, false, false])] input: [bool; 2]) -> bool;
| ^^^^^^^^^^^^^^^^^^^^ the trait `From<[bool; 3]>` is not implemented for `[bool; 2]`
| |
= help: the following other types implement trait `From<T>`: = help: the following other types implement trait `From<T>`:
<&'a [ascii::ascii_char::AsciiChar] as From<&'a ascii::ascii_str::AsciiStr>> <&'a [ascii::ascii_char::AsciiChar] as From<&'a ascii::ascii_str::AsciiStr>>
@ -14,5 +17,4 @@ error[E0277]: the trait bound `[bool; 2]: From<[bool; 3]>` is not satisfied
<[u128; 1] as From<ppv_lite86::x86_64::vec128_storage>> <[u128; 1] as From<ppv_lite86::x86_64::vec128_storage>>
<[u128; 2] as From<ppv_lite86::x86_64::vec256_storage>> <[u128; 2] as From<ppv_lite86::x86_64::vec256_storage>>
and 7 others and 7 others
= note: required because of the requirements on the impl of `Into<[bool; 2]>` for `[bool; 3]` = note: required for `[bool; 3]` to implement `Into<[bool; 2]>`
= note: this error originates in the attribute macro `graphql_interface` (in Nightly builds, run with -Z macro-backtrace for more info)

View file

@ -1,8 +1,11 @@
error[E0277]: the trait bound `[bool; 2]: From<[bool; 3]>` is not satisfied error[E0277]: the trait bound `[bool; 2]: From<[bool; 3]>` is not satisfied
--> fail/object/argument_wrong_default_array.rs:5:1 --> fail/object/argument_wrong_default_array.rs:7:41
| |
5 | #[graphql_object] 5 | #[graphql_object]
| ^^^^^^^^^^^^^^^^^ the trait `From<[bool; 3]>` is not implemented for `[bool; 2]` | ----------------- required by a bound introduced by this call
6 | impl ObjA {
7 | fn wrong(&self, #[graphql(default = [true, false, false])] input: [bool; 2]) -> bool {
| ^^^^^^^^^^^^^^^^^^^^ the trait `From<[bool; 3]>` is not implemented for `[bool; 2]`
| |
= help: the following other types implement trait `From<T>`: = help: the following other types implement trait `From<T>`:
<&'a [ascii::ascii_char::AsciiChar] as From<&'a ascii::ascii_str::AsciiStr>> <&'a [ascii::ascii_char::AsciiChar] as From<&'a ascii::ascii_str::AsciiStr>>
@ -14,5 +17,4 @@ error[E0277]: the trait bound `[bool; 2]: From<[bool; 3]>` is not satisfied
<[u128; 1] as From<ppv_lite86::x86_64::vec128_storage>> <[u128; 1] as From<ppv_lite86::x86_64::vec128_storage>>
<[u128; 2] as From<ppv_lite86::x86_64::vec256_storage>> <[u128; 2] as From<ppv_lite86::x86_64::vec256_storage>>
and 7 others and 7 others
= note: required because of the requirements on the impl of `Into<[bool; 2]>` for `[bool; 3]` = note: required for `[bool; 3]` to implement `Into<[bool; 2]>`
= note: this error originates in the attribute macro `graphql_object` (in Nightly builds, run with -Z macro-backtrace for more info)

View file

@ -1,8 +1,11 @@
error[E0277]: the trait bound `[bool; 2]: From<[bool; 3]>` is not satisfied error[E0277]: the trait bound `[bool; 2]: From<[bool; 3]>` is not satisfied
--> fail/subscription/argument_wrong_default_array.rs:10:1 --> fail/subscription/argument_wrong_default_array.rs:14:29
| |
10 | #[graphql_subscription] 10 | #[graphql_subscription]
| ^^^^^^^^^^^^^^^^^^^^^^^ the trait `From<[bool; 3]>` is not implemented for `[bool; 2]` | ----------------------- required by a bound introduced by this call
...
14 | #[graphql(default = [true, false, false])] input: [bool; 2],
| ^^^^^^^^^^^^^^^^^^^^ the trait `From<[bool; 3]>` is not implemented for `[bool; 2]`
| |
= help: the following other types implement trait `From<T>`: = help: the following other types implement trait `From<T>`:
<&'a [ascii::ascii_char::AsciiChar] as From<&'a ascii::ascii_str::AsciiStr>> <&'a [ascii::ascii_char::AsciiChar] as From<&'a ascii::ascii_str::AsciiStr>>
@ -14,5 +17,4 @@ error[E0277]: the trait bound `[bool; 2]: From<[bool; 3]>` is not satisfied
<[u128; 1] as From<ppv_lite86::x86_64::vec128_storage>> <[u128; 1] as From<ppv_lite86::x86_64::vec128_storage>>
<[u128; 2] as From<ppv_lite86::x86_64::vec256_storage>> <[u128; 2] as From<ppv_lite86::x86_64::vec256_storage>>
and 7 others and 7 others
= note: required because of the requirements on the impl of `Into<[bool; 2]>` for `[bool; 3]` = note: required for `[bool; 3]` to implement `Into<[bool; 2]>`
= note: this error originates in the attribute macro `graphql_subscription` (in Nightly builds, run with -Z macro-backtrace for more info)

View file

@ -6,7 +6,7 @@ publish = false
[dev-dependencies] [dev-dependencies]
async-trait = "0.1.39" async-trait = "0.1.39"
chrono = "0.4" chrono = { version = "0.4.20", default-features = false }
derive_more = "0.99" derive_more = "0.99"
fnv = "1.0" fnv = "1.0"
futures = "0.3" futures = "0.3"