Impl new machinery for Vec
[skip ci]
This commit is contained in:
parent
66c11ec782
commit
2d89de3403
6 changed files with 147 additions and 77 deletions
|
@ -85,6 +85,12 @@ where
|
||||||
field_path: Arc<FieldPath<'a>>,
|
field_path: Arc<FieldPath<'a>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'r, 'a, CX: ?Sized, SV> Executor<'r, 'a, CX, SV> {
|
||||||
|
pub(crate) fn current_type_reworked(&self) -> &TypeType<'a, SV> {
|
||||||
|
&self.current_type
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Error type for errors that occur during query execution
|
/// Error type for errors that occur during query execution
|
||||||
///
|
///
|
||||||
/// All execution errors contain the source position in the query of the field
|
/// All execution errors contain the source position in the query of the field
|
||||||
|
@ -1381,17 +1387,17 @@ impl<'r, S: 'r> Registry<'r, S> {
|
||||||
/// values of this type matches it.
|
/// values of this type matches it.
|
||||||
///
|
///
|
||||||
/// [`graphql::Type`]: resolve::Type
|
/// [`graphql::Type`]: resolve::Type
|
||||||
pub fn build_list_type_new<T, Info>(
|
pub fn wrap_list<'ti, T, TI>(
|
||||||
&mut self,
|
&mut self,
|
||||||
info: &Info,
|
type_info: &'ti TI,
|
||||||
expected_size: Option<usize>,
|
expected_size: Option<usize>,
|
||||||
) -> ListMeta<'r>
|
) -> MetaType<'r, S>
|
||||||
where
|
where
|
||||||
T: resolve::Type<Info, S> + ?Sized,
|
T: resolve::Type<TI, S> + ?Sized,
|
||||||
Info: ?Sized,
|
TI: ?Sized,
|
||||||
|
'ti: 'r,
|
||||||
{
|
{
|
||||||
todo!()
|
ListMeta::new(T::meta(self, type_info).into(), expected_size).into_meta()
|
||||||
//ListMeta::new(T::meta(self, info).as_type(), expected_size)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a [`NullableMeta`] type.
|
/// Creates a [`NullableMeta`] type.
|
||||||
|
|
|
@ -563,7 +563,7 @@ impl<'a, S> ScalarMeta<'a, S> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ListMeta<'a> {
|
impl<'a> ListMeta<'a> {
|
||||||
/// Build a new [`ListMeta`] type by wrapping the specified [`Type`].
|
/// Builds a new [`ListMeta`] type by wrapping the specified [`Type`].
|
||||||
///
|
///
|
||||||
/// Specifying `expected_size` will be used to ensure that values of this
|
/// Specifying `expected_size` will be used to ensure that values of this
|
||||||
/// type will always match it.
|
/// type will always match it.
|
||||||
|
@ -581,7 +581,7 @@ impl<'a> ListMeta<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> NullableMeta<'a> {
|
impl<'a> NullableMeta<'a> {
|
||||||
/// Build a new [`NullableMeta`] type by wrapping the specified [`Type`].
|
/// Builds a new [`NullableMeta`] type by wrapping the specified [`Type`].
|
||||||
pub fn new(of_type: Type<'a>) -> Self {
|
pub fn new(of_type: Type<'a>) -> Self {
|
||||||
Self { of_type }
|
Self { of_type }
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,28 +2,28 @@
|
||||||
|
|
||||||
use crate::{graphql, resolve, ExecutionResult, Executor, Selection};
|
use crate::{graphql, resolve, ExecutionResult, Executor, Selection};
|
||||||
|
|
||||||
/*
|
pub fn resolve_list<'t, T, TI, CX, SV, BH, I>(
|
||||||
pub fn resolve_list<'t, T, S, Info, Ctx, I>(
|
|
||||||
iter: I,
|
iter: I,
|
||||||
selection_set: Option<&[Selection<'_, S>]>,
|
selection_set: Option<&[Selection<'_, SV>]>,
|
||||||
info: &Info,
|
type_info: &TI,
|
||||||
executor: &Executor<Ctx, S>,
|
executor: &Executor<CX, SV>,
|
||||||
) -> ExecutionResult<S>
|
) -> ExecutionResult<SV>
|
||||||
where
|
where
|
||||||
I: Iterator<Item = &'t T> + ExactSizeIterator,
|
I: Iterator<Item = &'t T> + ExactSizeIterator,
|
||||||
T: resolve::Value<Info, Ctx, S> + ?Sized + 't,
|
T: resolve::Value<TI, CX, SV, BH> + ?Sized + 't,
|
||||||
Info: ?Sized,
|
TI: ?Sized,
|
||||||
Ctx: ?Sized,
|
CX: ?Sized,
|
||||||
|
BH: ?Sized,
|
||||||
{
|
{
|
||||||
let is_non_null = executor
|
let is_non_null = executor
|
||||||
.current_type_new()
|
.current_type_reworked()
|
||||||
.list_contents()
|
.list_contents()
|
||||||
.ok_or("Iterating over non-list type")?
|
.ok_or("Iterating over non-list type")?
|
||||||
.is_non_null();
|
.is_non_null();
|
||||||
|
|
||||||
let mut values = Vec::with_capacity(iter.len());
|
let mut values = Vec::with_capacity(iter.len());
|
||||||
for v in iter {
|
for v in iter {
|
||||||
let val = v.resolve_value(selection_set, info, executor)?;
|
let val = v.resolve_value(selection_set, type_info, executor)?;
|
||||||
if is_non_null && val.is_null() {
|
if is_non_null && val.is_null() {
|
||||||
return Err("Resolved `null` on non-null type".into());
|
return Err("Resolved `null` on non-null type".into());
|
||||||
}
|
}
|
||||||
|
@ -32,28 +32,32 @@ where
|
||||||
Ok(graphql::Value::list(values))
|
Ok(graphql::Value::list(values))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn resolve_list_async<'a, 't, T, S, Info, Ctx, I>(
|
pub async fn resolve_list_async<'t, 'r, T, TI, CX, SV, BH, I>(
|
||||||
iter: I,
|
iter: I,
|
||||||
selection_set: Option<&[Selection<'_, S>]>,
|
selection_set: Option<&[Selection<'_, SV>]>,
|
||||||
info: &'a Info,
|
type_info: &'r TI,
|
||||||
executor: &'a Executor<'a, 'a, Ctx, S>,
|
executor: &'r Executor<'r, '_, CX, SV>,
|
||||||
) -> ExecutionResult<S>
|
) -> ExecutionResult<SV>
|
||||||
where
|
where
|
||||||
I: Iterator<Item = &'t T> + ExactSizeIterator,
|
I: Iterator<Item = &'t T> + ExactSizeIterator,
|
||||||
T: resolve::ValueAsync<Info, Ctx, S> + ?Sized + 't,
|
T: resolve::ValueAsync<TI, CX, SV, BH> + ?Sized + 't,
|
||||||
Info: ?Sized,
|
TI: ?Sized,
|
||||||
Ctx: ?Sized,
|
CX: ?Sized,
|
||||||
|
BH: ?Sized,
|
||||||
{
|
{
|
||||||
use futures::stream::{FuturesOrdered, StreamExt as _};
|
use futures::stream::{FuturesOrdered, StreamExt as _};
|
||||||
|
|
||||||
let is_non_null = executor
|
let is_non_null = executor
|
||||||
.current_type_new()
|
.current_type_reworked()
|
||||||
.list_contents()
|
.list_contents()
|
||||||
.ok_or("Iterating over non-list type")?
|
.ok_or("Iterating over non-list type")?
|
||||||
.is_non_null();
|
.is_non_null();
|
||||||
|
|
||||||
let mut futs = iter
|
let mut futs = iter
|
||||||
.map(|v| async move { v.resolve_value_async(selection_set, info, executor).await })
|
.map(|v| async move {
|
||||||
|
v.resolve_value_async(selection_set, type_info, executor)
|
||||||
|
.await
|
||||||
|
})
|
||||||
.collect::<FuturesOrdered<_>>();
|
.collect::<FuturesOrdered<_>>();
|
||||||
|
|
||||||
let mut values = Vec::with_capacity(futs.len());
|
let mut values = Vec::with_capacity(futs.len());
|
||||||
|
@ -66,4 +70,3 @@ where
|
||||||
}
|
}
|
||||||
Ok(graphql::Value::list(values))
|
Ok(graphql::Value::list(values))
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ mod ref_mut;
|
||||||
mod result;
|
mod result;
|
||||||
mod slice;
|
mod slice;
|
||||||
mod r#str;
|
mod r#str;
|
||||||
mod vec;
|
pub mod vec;
|
||||||
|
|
||||||
pub mod async_await;
|
pub mod async_await;
|
||||||
pub mod base;
|
pub mod base;
|
||||||
|
|
|
@ -1,114 +1,175 @@
|
||||||
//! GraphQL implementation for [`Vec`].
|
//! GraphQL implementation for [`Vec`].
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
behavior,
|
||||||
executor::{ExecutionResult, Executor, Registry},
|
executor::{ExecutionResult, Executor, Registry},
|
||||||
graphql, reflect, resolve,
|
graphql, reflect, resolve,
|
||||||
schema::meta::MetaType,
|
schema::meta::MetaType,
|
||||||
BoxFuture, Selection,
|
BoxFuture, FieldError, IntoFieldError, Selection,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::iter;
|
use super::iter;
|
||||||
|
|
||||||
/*
|
impl<T, TI, SV, BH> resolve::Type<TI, SV, BH> for Vec<T>
|
||||||
impl<T, Info, S> resolve::Type<Info, S> for Vec<T>
|
|
||||||
where
|
where
|
||||||
T: resolve::Type<Info, S>,
|
T: resolve::Type<TI, SV, BH>,
|
||||||
Info: ?Sized,
|
TI: ?Sized,
|
||||||
|
BH: ?Sized,
|
||||||
{
|
{
|
||||||
fn meta<'r>(registry: &mut Registry<'r, S>, info: &Info) -> MetaType<'r, S>
|
fn meta<'r, 'ti: 'r>(registry: &mut Registry<'r, SV>, type_info: &'ti TI) -> MetaType<'r, SV>
|
||||||
where
|
where
|
||||||
S: 'r,
|
SV: 'r,
|
||||||
{
|
{
|
||||||
registry.build_list_type_new::<T, _>(info, None).into_meta()
|
registry.wrap_list::<behavior::Coerce<T, BH>, _>(type_info, None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, Info, Ctx, S> resolve::Value<Info, Ctx, S> for Vec<T>
|
impl<T, TI, CX, SV, BH> resolve::Value<TI, CX, SV, BH> for Vec<T>
|
||||||
where
|
where
|
||||||
T: resolve::Value<Info, Ctx, S>,
|
T: resolve::Value<TI, CX, SV, BH>,
|
||||||
Info: ?Sized,
|
TI: ?Sized,
|
||||||
Ctx: ?Sized,
|
CX: ?Sized,
|
||||||
|
BH: ?Sized,
|
||||||
{
|
{
|
||||||
fn resolve_value(
|
fn resolve_value(
|
||||||
&self,
|
&self,
|
||||||
selection_set: Option<&[Selection<'_, S>]>,
|
selection_set: Option<&[Selection<'_, SV>]>,
|
||||||
info: &Info,
|
type_info: &TI,
|
||||||
executor: &Executor<Ctx, S>,
|
executor: &Executor<CX, SV>,
|
||||||
) -> ExecutionResult<S> {
|
) -> ExecutionResult<SV> {
|
||||||
iter::resolve_list(self.iter(), selection_set, info, executor)
|
iter::resolve_list(self.iter(), selection_set, type_info, executor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, Info, Ctx, S> resolve::ValueAsync<Info, Ctx, S> for Vec<T>
|
impl<T, TI, CX, SV, BH> resolve::ValueAsync<TI, CX, SV, BH> for Vec<T>
|
||||||
where
|
where
|
||||||
T: resolve::ValueAsync<Info, Ctx, S> + Sync,
|
T: resolve::ValueAsync<TI, CX, SV, BH> + Sync,
|
||||||
Info: Sync + ?Sized,
|
TI: Sync + ?Sized,
|
||||||
Ctx: Sync + ?Sized,
|
CX: Sync + ?Sized,
|
||||||
S: Send + Sync,
|
SV: Send + Sync,
|
||||||
|
BH: ?Sized + 'static, // TODO: Lift `'static` bound if possible.
|
||||||
{
|
{
|
||||||
fn resolve_value_async<'r>(
|
fn resolve_value_async<'r>(
|
||||||
&'r self,
|
&'r self,
|
||||||
selection_set: Option<&'r [Selection<'_, S>]>,
|
selection_set: Option<&'r [Selection<'_, SV>]>,
|
||||||
info: &'r Info,
|
type_info: &'r TI,
|
||||||
executor: &'r Executor<Ctx, S>,
|
executor: &'r Executor<CX, SV>,
|
||||||
) -> BoxFuture<'r, ExecutionResult<S>> {
|
) -> BoxFuture<'r, ExecutionResult<SV>> {
|
||||||
Box::pin(iter::resolve_list_async(
|
Box::pin(iter::resolve_list_async(
|
||||||
self.iter(),
|
self.iter(),
|
||||||
selection_set,
|
selection_set,
|
||||||
info,
|
type_info,
|
||||||
executor,
|
executor,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, S> resolve::ToInputValue<S> for Vec<T>
|
impl<T, SV, BH> resolve::ToInputValue<SV, BH> for Vec<T>
|
||||||
where
|
where
|
||||||
T: resolve::ToInputValue<S>,
|
T: resolve::ToInputValue<SV, BH>,
|
||||||
|
BH: ?Sized,
|
||||||
{
|
{
|
||||||
fn to_input_value(&self) -> graphql::InputValue<S> {
|
fn to_input_value(&self) -> graphql::InputValue<SV> {
|
||||||
graphql::InputValue::list(self.iter().map(T::to_input_value))
|
graphql::InputValue::list(self.iter().map(T::to_input_value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'i, T, SV, BH> resolve::InputValue<'i, SV, BH> for Vec<T>
|
||||||
impl<'i, T, Info, S> graphql::InputType<'i, Info, S> for Vec<T>
|
|
||||||
where
|
where
|
||||||
T: graphql::InputType<'i, Info, S>,
|
T: resolve::InputValue<'i, SV, BH>,
|
||||||
Info: ?Sized,
|
SV: 'i,
|
||||||
|
BH: ?Sized,
|
||||||
|
{
|
||||||
|
type Error = TryFromInputValueError<T::Error>;
|
||||||
|
|
||||||
|
fn try_from_input_value(v: &'i graphql::InputValue<SV>) -> Result<Self, Self::Error> {
|
||||||
|
match v {
|
||||||
|
graphql::InputValue::List(l) => l
|
||||||
|
.iter()
|
||||||
|
.map(|i| T::try_from_input_value(&i.item).map_err(TryFromInputValueError::Item))
|
||||||
|
.collect(),
|
||||||
|
// See "Input Coercion" on List types:
|
||||||
|
// https://spec.graphql.org/October2021#sec-Combining-List-and-Non-Null
|
||||||
|
graphql::InputValue::Null => Err(TryFromInputValueError::IsNull),
|
||||||
|
other => T::try_from_input_value(other)
|
||||||
|
.map(|e| vec![e])
|
||||||
|
.map_err(TryFromInputValueError::Item),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'i, T, TI, SV, BH> graphql::InputType<'i, TI, SV, BH> for Vec<T>
|
||||||
|
where
|
||||||
|
T: graphql::InputType<'i, TI, SV, BH>,
|
||||||
|
TI: ?Sized,
|
||||||
|
SV: 'i,
|
||||||
|
BH: ?Sized,
|
||||||
{
|
{
|
||||||
fn assert_input_type() {
|
fn assert_input_type() {
|
||||||
T::assert_input_type()
|
T::assert_input_type()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T, TI, CX, SV, BH> graphql::OutputType<TI, CX, SV, BH> for Vec<T>
|
||||||
impl<T, S> graphql::OutputType<S> for Vec<T>
|
|
||||||
where
|
where
|
||||||
T: graphql::OutputType<S>,
|
T: graphql::OutputType<TI, CX, SV, BH>,
|
||||||
|
TI: ?Sized,
|
||||||
|
CX: ?Sized,
|
||||||
|
BH: ?Sized,
|
||||||
|
Self: resolve::ValueAsync<TI, CX, SV, BH>,
|
||||||
{
|
{
|
||||||
fn assert_output_type() {
|
fn assert_output_type() {
|
||||||
T::assert_output_type()
|
T::assert_output_type()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, S> reflect::BaseType<S> for Vec<T>
|
impl<T, BH> reflect::BaseType<BH> for Vec<T>
|
||||||
where
|
where
|
||||||
T: reflect::BaseType<S>,
|
T: reflect::BaseType<BH>,
|
||||||
|
BH: ?Sized,
|
||||||
{
|
{
|
||||||
const NAME: reflect::Type = T::NAME;
|
const NAME: reflect::Type = T::NAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, S> reflect::BaseSubTypes<S> for Vec<T>
|
impl<T, BH> reflect::BaseSubTypes<BH> for Vec<T>
|
||||||
where
|
where
|
||||||
T: reflect::BaseSubTypes<S>,
|
T: reflect::BaseSubTypes<BH>,
|
||||||
|
BH: ?Sized,
|
||||||
{
|
{
|
||||||
const NAMES: reflect::Types = T::NAMES;
|
const NAMES: reflect::Types = T::NAMES;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, S> reflect::WrappedType<S> for Vec<T>
|
impl<T, BH> reflect::WrappedType<BH> for Vec<T>
|
||||||
where
|
where
|
||||||
T: reflect::WrappedType<S>,
|
T: reflect::WrappedType<BH>,
|
||||||
|
BH: ?Sized,
|
||||||
{
|
{
|
||||||
const VALUE: reflect::WrappedValue = reflect::wrap::list(T::VALUE);
|
const VALUE: reflect::WrappedValue = reflect::wrap::list(T::VALUE);
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
/// Possible errors of converting a [`graphql::InputValue`] into a [`Vec`].
|
||||||
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
|
pub enum TryFromInputValueError<E> {
|
||||||
|
/// [`graphql::InputValue`] cannot be [`Null`].
|
||||||
|
///
|
||||||
|
/// See ["Combining List and Non-Null" section of spec][0].
|
||||||
|
///
|
||||||
|
/// [`Null`]: [`InputValue::Null`]
|
||||||
|
/// [0]: https://spec.graphql.org/October2021#sec-Combining-List-and-Non-Null
|
||||||
|
IsNull,
|
||||||
|
|
||||||
|
/// Error of converting a [`graphql::InputValue::List`]'s item.
|
||||||
|
Item(E),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E, SV> IntoFieldError<SV> for TryFromInputValueError<E>
|
||||||
|
where
|
||||||
|
E: IntoFieldError<SV>,
|
||||||
|
{
|
||||||
|
fn into_field_error(self) -> FieldError<SV> {
|
||||||
|
match self {
|
||||||
|
Self::IsNull => "Failed to convert into `Vec`: Value cannot be `null`".into(),
|
||||||
|
Self::Item(e) => e.into_field_error(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
//! Common functions, definitions and extensions for code generation, used by this crate.
|
//! Common functions, definitions and extensions for code generation, used by this crate.
|
||||||
|
|
||||||
|
pub(crate) mod behavior;
|
||||||
pub(crate) mod field;
|
pub(crate) mod field;
|
||||||
pub(crate) mod gen;
|
pub(crate) mod gen;
|
||||||
pub(crate) mod parse;
|
pub(crate) mod parse;
|
||||||
pub(crate) mod scalar;
|
pub(crate) mod scalar;
|
||||||
pub(crate) mod behavior;
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue