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

View file

@ -8,7 +8,7 @@ publish = false
[dependencies]
async-stream = "0.3"
env_logger = "0.9"
futures = "0.3.1"
futures = "0.3"
juniper = { path = "../../juniper" }
juniper_graphql_ws = { path = "../../juniper_graphql_ws" }
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"
bigdecimal = { version = "0.3", 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 }
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 }
graphql-parser = { version = "0.4", optional = true }
indexmap = { version = "1.0", features = ["serde-1"] }
@ -62,7 +62,7 @@ getrandom = { version = "0.2", features = ["js"] }
[dev-dependencies]
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"
serde_json = "1.0.2"
tokio = { version = "1.0", features = ["macros", "time", "rt-multi-thread"] }

View file

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

View file

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

View file

@ -5,7 +5,6 @@ use crate::{
reflect, Arguments, BoxFuture, ExecutionResult, Executor, FieldResult, IntoFieldError,
Registry, Selection,
};
use juniper::resolve;
pub trait Type<TypeInfo: ?Sized, ScalarValue, Behavior: ?Sized = behavior::Standard> {
fn meta<'r, 'ti: 'r>(
@ -54,6 +53,12 @@ pub trait ValueAsync<
) -> 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<
TypeInfo: ?Sized,
Context: ?Sized,
@ -204,75 +209,3 @@ pub trait InputValueAsRef<ScalarValue, Behavior: ?Sized = behavior::Standard> {
pub trait ScalarToken<ScalarValue, Behavior: ?Sized = behavior::Standard> {
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,
meta::MetaType,
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>
@ -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>
where
T: resolve::ConcreteValue<TI, CX, SV, BH> + ?Sized,

View file

@ -12,7 +12,7 @@ use crate::{
executor::{ExecutionResult, Executor, Registry},
graphql, reflect, resolve,
schema::meta::MetaType,
BoxFuture, FieldError, IntoFieldError, Selection,
BoxFuture, FieldError, FieldResult, IntoFieldError, Selection,
};
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]
where
T: resolve::ToInputValue<SV, BH>,

View file

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

View file

@ -4,7 +4,8 @@ use crate::{
graphql,
meta::MetaType,
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>
@ -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>
where
T: resolve::ConcreteValue<TI, CX, SV, BH> + ?Sized,

View file

@ -6,7 +6,8 @@ use crate::{
graphql,
meta::MetaType,
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>
@ -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>
where
T: resolve::ConcreteValue<TI, CX, SV, BH> + ToOwned + ?Sized + 'me,

View file

@ -15,7 +15,7 @@ use crate::{
base::{GraphQLType, GraphQLValue},
marker::IsInputType,
},
BoxFuture, ScalarValue, Selection,
BoxFuture, FieldResult, ScalarValue, Selection,
};
/// [`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>
where
T: resolve::ToInputValue<SV, BH>,

View file

@ -7,7 +7,7 @@ use crate::{
executor::{ExecutionResult, Executor, Registry},
graphql, reflect, resolve,
schema::meta::MetaType,
BoxFuture, Selection,
BoxFuture, FieldResult, Selection,
};
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>
where
T: resolve::ToInputValue<SV, BH>,

View file

@ -6,7 +6,8 @@ use crate::{
graphql,
meta::MetaType,
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>
@ -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>
where
T: resolve::ConcreteValue<TI, CX, SV, BH> + ?Sized,

View file

@ -6,7 +6,8 @@ use crate::{
graphql,
meta::MetaType,
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
@ -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
where
T: resolve::ConcreteValue<TI, CX, SV, BH> + ?Sized,

View file

@ -6,7 +6,8 @@ use crate::{
graphql,
meta::MetaType,
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
@ -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
where
T: resolve::ConcreteValue<TI, CX, SV, BH> + ?Sized,

View file

@ -1,6 +1,18 @@
//! 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>
where

View file

@ -5,7 +5,7 @@ use crate::{
executor::{ExecutionResult, Executor, Registry},
graphql, reflect, resolve,
schema::meta::MetaType,
BoxFuture, FieldError, IntoFieldError, Selection,
BoxFuture, FieldError, FieldResult, IntoFieldError, Selection,
};
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>
where
T: resolve::ToInputValue<SV, BH>,

View file

@ -27,7 +27,7 @@ actix-http = "3.0"
actix-web = "4.0"
actix-web-actors = "4.1.0"
anyhow = "1.0"
futures = "0.3"
futures = "0.3.22"
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 }
http = "0.2.4"

View file

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

View file

@ -417,6 +417,7 @@ impl ToTokens for Definition {
self.impl_resolve_type_name().to_tokens(into);
self.impl_resolve_value().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_input_value().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
/// [GraphQL enum][0].
///

View file

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

View file

@ -351,6 +351,7 @@ impl ToTokens for Definition {
self.impl_resolve_type_name().to_tokens(into);
self.impl_resolve_value().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_input_value().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
/// [GraphQL scalar][1].
///

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -23,7 +23,7 @@ subscriptions = ["juniper_graphql_ws"]
[dependencies]
anyhow = "1.0"
futures = "0.3.1"
futures = "0.3.22"
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 }
serde = { version = "1.0.75", features = ["derive"] }

View file

@ -8,7 +8,7 @@ publish = false
rustversion = "1.0"
[dev-dependencies]
futures = "0.3.1"
futures = "0.3"
juniper = { path = "../../juniper" }
serde_json = "1.0"
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
--> fail/interface/trait/argument_wrong_default_array.rs:3:1
--> fail/interface/trait/argument_wrong_default_array.rs:5:41
|
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>`:
<&'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; 2] as From<ppv_lite86::x86_64::vec256_storage>>
and 7 others
= note: required because of the requirements on the impl of `Into<[bool; 2]>` for `[bool; 3]`
= note: this error originates in the attribute macro `graphql_interface` (in Nightly builds, run with -Z macro-backtrace for more info)
= note: required for `[bool; 3]` to implement `Into<[bool; 2]>`

View file

@ -1,8 +1,11 @@
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]
| ^^^^^^^^^^^^^^^^^ 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>`:
<&'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; 2] as From<ppv_lite86::x86_64::vec256_storage>>
and 7 others
= note: required because of the requirements on the impl of `Into<[bool; 2]>` for `[bool; 3]`
= note: this error originates in the attribute macro `graphql_object` (in Nightly builds, run with -Z macro-backtrace for more info)
= note: required for `[bool; 3]` to implement `Into<[bool; 2]>`

View file

@ -1,8 +1,11 @@
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]
| ^^^^^^^^^^^^^^^^^^^^^^^ 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>`:
<&'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; 2] as From<ppv_lite86::x86_64::vec256_storage>>
and 7 others
= note: required because of the requirements on the impl of `Into<[bool; 2]>` for `[bool; 3]`
= note: this error originates in the attribute macro `graphql_subscription` (in Nightly builds, run with -Z macro-backtrace for more info)
= note: required for `[bool; 3]` to implement `Into<[bool; 2]>`

View file

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