Poking with parsing input

This commit is contained in:
tyranron 2022-05-12 18:53:19 +03:00
parent ffc42b16a1
commit 912d31f66b
No known key found for this signature in database
GPG key ID: 762E144FB230A4F0
9 changed files with 123 additions and 37 deletions

View file

@ -4,7 +4,6 @@ use std::{
borrow::Cow, borrow::Cow,
cmp::Ordering, cmp::Ordering,
collections::HashMap, collections::HashMap,
convert::TryFrom,
fmt::{Debug, Display}, fmt::{Debug, Display},
sync::{Arc, RwLock}, sync::{Arc, RwLock},
}; };
@ -1295,22 +1294,30 @@ impl<'r, S: 'r> Registry<'r, S> {
ScalarMeta::new::<T>(Cow::Owned(name.to_string())) ScalarMeta::new::<T>(Cow::Owned(name.to_string()))
} }
/*
/// Builds a [`ScalarMeta`] information for the specified [`graphql::Type`]. /// Builds a [`ScalarMeta`] information for the specified [`graphql::Type`].
/// ///
/// [`graphql::Type`]: resolve::Type /// [`graphql::Type`]: resolve::Type
pub fn build_scalar_type_new<'info, T, Info>(&mut self, info: &Info) -> ScalarMeta<'r, S> pub fn build_scalar_type_new<T, Info>(&mut self, info: &Info) -> ScalarMeta<'r, S>
where where
T: resolve::TypeName<Info> T: resolve::TypeName<Info> + resolve::ScalarToken<S> + resolve::InputValueOwned<S>,
+ resolve::ScalarToken<S>
+ for<'inp> resolve::InputValue<'inp, S>,
for<'i> <T as TryFrom<&'i InputValue<S>>>::Error: IntoFieldError<S>,
Info: ?Sized, Info: ?Sized,
{ {
// TODO: Allow using references. // TODO: Allow using references.
ScalarMeta::new_new::<T, _>(T::type_name(info).to_owned()) ScalarMeta::new_new::<T, _>(T::type_name(info).to_owned())
} }
*/
/// Builds a [`ScalarMeta`] information for the [`?Sized`] specified
/// [`graphql::Type`].
///
/// [`graphql::Type`]: resolve::Type
pub fn build_scalar_type_unsized<T, Info>(&mut self, info: &Info) -> ScalarMeta<'r, S>
where
T: resolve::TypeName<Info> + resolve::ScalarToken<S> + resolve::InputValueAsRef<S> + ?Sized,
Info: ?Sized,
{
// TODO: Allow using references.
ScalarMeta::new_unsized::<T, _>(T::type_name(info).to_owned())
}
/// Creates a [`ListMeta`] type. /// Creates a [`ListMeta`] type.
/// ///

View file

@ -82,12 +82,12 @@ pub use crate::{
async_await::{GraphQLTypeAsync, GraphQLValueAsync}, async_await::{GraphQLTypeAsync, GraphQLValueAsync},
base::{Arguments, GraphQLType, GraphQLValue, TypeKind}, base::{Arguments, GraphQLType, GraphQLValue, TypeKind},
marker::{self, GraphQLInterface, GraphQLObject, GraphQLUnion}, marker::{self, GraphQLInterface, GraphQLObject, GraphQLUnion},
Nullable,
scalars::{EmptyMutation, EmptySubscription, ID}, scalars::{EmptyMutation, EmptySubscription, ID},
subscriptions::{ subscriptions::{
ExecutionOutput, GraphQLSubscriptionType, GraphQLSubscriptionValue, ExecutionOutput, GraphQLSubscriptionType, GraphQLSubscriptionValue,
SubscriptionConnection, SubscriptionCoordinator, SubscriptionConnection, SubscriptionCoordinator,
}, },
Nullable,
}, },
validation::RuleError, validation::RuleError,
value::{DefaultScalarValue, Object, ParseScalarResult, ParseScalarValue, ScalarValue, Value}, value::{DefaultScalarValue, Object, ParseScalarResult, ParseScalarValue, ScalarValue, Value},

View file

@ -1,10 +1,9 @@
use std::convert::TryFrom;
use crate::{ use crate::{
graphql, graphql,
meta::MetaType, meta::MetaType,
parser::{self, ParseError}, parser::{self, ParseError},
Arguments, BoxFuture, DefaultScalarValue, ExecutionResult, Executor, Registry, Selection, Arguments, BoxFuture, DefaultScalarValue, ExecutionResult, Executor, IntoFieldError, Registry,
Selection,
}; };
pub trait Type<Info: ?Sized, S = DefaultScalarValue> { pub trait Type<Info: ?Sized, S = DefaultScalarValue> {
@ -84,7 +83,7 @@ pub trait ScalarToken<S = DefaultScalarValue> {
} }
pub trait InputValue<'input, S: 'input = DefaultScalarValue>: Sized { pub trait InputValue<'input, S: 'input = DefaultScalarValue>: Sized {
type Error; type Error: IntoFieldError<S>;
fn try_from_input_value(v: &'input graphql::InputValue<S>) -> Result<Self, Self::Error>; fn try_from_input_value(v: &'input graphql::InputValue<S>) -> Result<Self, Self::Error>;
@ -98,13 +97,24 @@ pub trait InputValueOwned<S = DefaultScalarValue>: for<'i> InputValue<'i, S> {}
impl<T, S> InputValueOwned<S> for T where T: for<'i> InputValue<'i, S> {} impl<T, S> InputValueOwned<S> for T where T: for<'i> InputValue<'i, S> {}
pub trait InputValueAsRef<S = DefaultScalarValue> { pub trait InputValueAsRef<S = DefaultScalarValue> {
type Error; type Error: IntoFieldError<S>;
fn try_from_input_value(v: &graphql::InputValue<S>) -> Result<&Self, Self::Error>; fn try_from_input_value(v: &graphql::InputValue<S>) -> Result<&Self, Self::Error>;
fn try_from_implicit_null() -> Result<&'static Self, Self::Error> fn try_from_implicit_null<'a>() -> Result<&'a Self, Self::Error>
where S: 'static where
S: 'a,
{ {
Self::try_from_input_value(&graphql::InputValue::<S>::Null) Self::try_from_input_value(&graphql::InputValue::<S>::Null)
} }
} }
/*
impl<T, S> InputValueAsRef<S> for T where T: InputValueOwned<S> {
type Error = <T as InputValueOwned<S>>::Error;
fn try_from_input_value(v: &graphql::InputValue<S>) -> Result<&Self, Self::Error> {
<T as InputValueOwned<S>>::try_from_input_value(v).as_ref()
}
}
*/

View file

@ -2,7 +2,6 @@
use std::{ use std::{
borrow::{Cow, ToOwned}, borrow::{Cow, ToOwned},
convert::TryFrom,
fmt, fmt,
}; };
@ -449,28 +448,42 @@ impl<'a, S> ScalarMeta<'a, S> {
} }
} }
/*
/// Builds a new [`ScalarMeta`] information with the specified `name`. /// Builds a new [`ScalarMeta`] information with the specified `name`.
// TODO: Use `impl Into<Cow<'a, str>>` argument once feature // TODO: Use `impl Into<Cow<'a, str>>` argument once feature
// `explicit_generic_args_with_impl_trait` hits stable: // `explicit_generic_args_with_impl_trait` hits stable:
// https://github.com/rust-lang/rust/issues/83701 // https://github.com/rust-lang/rust/issues/83701
pub fn new_new<T, N>(name: N) -> Self pub fn new_new<T, N>(name: N) -> Self
where where
T: resolve::ValidateInputValue<S> + resolve::ScalarToken<S>, T: resolve::InputValueOwned<S> + resolve::ScalarToken<S>,
//T: for<'inp> resolve::InputValue<'inp, S> + resolve::ScalarToken<S>,
//for<'inp> <T as TryFrom<&'inp InputValue<S>>>::Error: IntoFieldError<S>,
Cow<'a, str>: From<N>, Cow<'a, str>: From<N>,
{ {
Self { Self {
name: name.into(), name: name.into(),
description: None, description: None,
specified_by_url: None, specified_by_url: None,
try_parse_fn: <T as resolve::ValidateInputValue<S>>::validate_input_value, try_parse_fn: try_parse_fn_new::<S, T>,
//try_parse_fn: |inp| try_parse_fn_new::<S, T>(inp), parse_fn: <T as resolve::ScalarToken<S>>::parse_scalar_token,
}
}
/// Builds a new [`ScalarMeta`] information with the specified `name` for
/// the [`?Sized`] `T`ype that may only be parsed as a reference.
// TODO: Use `impl Into<Cow<'a, str>>` argument once feature
// `explicit_generic_args_with_impl_trait` hits stable:
// https://github.com/rust-lang/rust/issues/83701
pub fn new_unsized<T, N>(name: N) -> Self
where
T: resolve::InputValueAsRef<S> + resolve::ScalarToken<S> + ?Sized,
Cow<'a, str>: From<N>,
{
Self {
name: name.into(),
description: None,
specified_by_url: None,
try_parse_fn: try_parse_unsized_fn::<S, T>,
parse_fn: <T as resolve::ScalarToken<S>>::parse_scalar_token, parse_fn: <T as resolve::ScalarToken<S>>::parse_scalar_token,
} }
} }
*/
/// Sets the `description` of this [`ScalarMeta`] type. /// Sets the `description` of this [`ScalarMeta`] type.
/// ///
@ -824,12 +837,20 @@ where
.map_err(T::Error::into_field_error) .map_err(T::Error::into_field_error)
} }
/* fn try_parse_fn_new<S, T>(v: &InputValue<S>) -> Result<(), FieldError<S>>
fn try_parse_fn_new<'inp, 'b: 'inp, S: 'inp, T>(v: &'b InputValue<S>) -> Result<(), FieldError<S>>
where where
T: resolve::InputValue<'inp, S>, T: resolve::InputValueOwned<S>,
T::Error: IntoFieldError<S>,
{ {
T::try_from(v).map(drop).map_err(T::Error::into_field_error) T::try_from_input_value(v)
.map(drop)
.map_err(T::Error::into_field_error)
}
fn try_parse_unsized_fn<S, T>(v: &InputValue<S>) -> Result<(), FieldError<S>>
where
T: resolve::InputValueAsRef<S> + ?Sized,
{
T::try_from_input_value(v)
.map(drop)
.map_err(T::Error::into_field_error)
} }
*/

View file

@ -149,6 +149,22 @@ where
} }
} }
// TODO: how to parse unsized?
impl<'inp, T, S: 'inp> resolve::InputValue<'inp, S> for Box<T>
where
T: resolve::InputValue<'inp, S>,
{
type Error = <T as resolve::InputValue<'inp, S>>::Error;
fn try_from_input_value(v: &'inp graphql::InputValue<S>) -> Result<Self, Self::Error> {
<T as resolve::InputValue<'inp, S>>::try_from_input_value(v).map(Self::new)
}
fn try_from_implicit_null() -> Result<Self, Self::Error> {
<T as resolve::InputValue<'inp, S>>::try_from_implicit_null().map(Self::new)
}
}
impl<T, S> graphql::InputType<S> for Box<T> impl<T, S> graphql::InputType<S> for Box<T>
where where
T: graphql::InputType<S> + ?Sized, T: graphql::InputType<S> + ?Sized,

View file

@ -1,5 +1,5 @@
mod array;
mod arc; mod arc;
mod array;
mod r#box; mod r#box;
pub mod iter; pub mod iter;
mod nullable; mod nullable;

View file

@ -324,6 +324,25 @@ where
} }
} }
impl<'inp, T, S: 'inp> resolve::InputValue<'inp, S> for Nullable<T>
where
T: resolve::InputValue<'inp, S>,
{
type Error = <T as resolve::InputValue<'inp, S>>::Error;
fn try_from_input_value(v: &'inp InputValue<S>) -> Result<Self, Self::Error> {
if v.is_null() {
Ok(Self::ExplicitNull)
} else {
<T as resolve::InputValue<'inp, S>>::try_from_input_value(v).map(Self::Some)
}
}
fn try_from_implicit_null() -> Result<Self, Self::Error> {
Ok(Self::ImplicitNull)
}
}
impl<T, S> graphql::InputType<S> for Nullable<T> impl<T, S> graphql::InputType<S> for Nullable<T>
where where
T: graphql::InputType<S>, T: graphql::InputType<S>,

View file

@ -61,6 +61,21 @@ where
} }
} }
impl<'inp, T, S: 'inp> resolve::InputValue<'inp, S> for Option<T>
where
T: resolve::InputValue<'inp, S>,
{
type Error = <T as resolve::InputValue<'inp, S>>::Error;
fn try_from_input_value(v: &'inp graphql::InputValue<S>) -> Result<Self, Self::Error> {
if v.is_null() {
Ok(None)
} else {
<T as resolve::InputValue<'inp, S>>::try_from_input_value(v).map(Some)
}
}
}
impl<T, S> graphql::InputType<S> for Option<T> impl<T, S> graphql::InputType<S> for Option<T>
where where
T: graphql::InputType<S>, T: graphql::InputType<S>,

View file

@ -2,16 +2,13 @@
//! //!
//! [`str`]: primitive@std::str //! [`str`]: primitive@std::str
use std::convert::TryFrom;
use futures::future; use futures::future;
use crate::{ use crate::{
graphql, graphql,
meta::MetaType, meta::MetaType,
parser::{ParseError, ScalarToken}, parser::{ParseError, ScalarToken},
resolve, BoxFuture, ExecutionResult, Executor, IntoFieldError, Registry, ScalarValue, resolve, BoxFuture, ExecutionResult, Executor, Registry, ScalarValue, Selection,
Selection,
}; };
impl<Info: ?Sized, S: ScalarValue> resolve::Type<Info, S> for str { impl<Info: ?Sized, S: ScalarValue> resolve::Type<Info, S> for str {
@ -19,8 +16,9 @@ impl<Info: ?Sized, S: ScalarValue> resolve::Type<Info, S> for str {
where where
S: 'r, S: 'r,
{ {
// registry.build_scalar_type_new::<&Self, _>(info).into_meta() registry
unimplemented!() .build_scalar_type_unsized::<Self, _>(info)
.into_meta()
} }
} }