Rework meta creation [skip ci]

This commit is contained in:
tyranron 2022-06-17 16:04:48 +02:00
parent 067b1e532a
commit 25404eb4a7
No known key found for this signature in database
GPG key ID: 762E144FB230A4F0
12 changed files with 114 additions and 43 deletions

View file

@ -2,20 +2,38 @@
use std::{marker::PhantomData, sync::atomic::AtomicPtr};
use crate::{meta::MetaType, resolve, Registry};
/// Default standard behavior of GraphQL types implementation.
#[derive(Debug)]
pub enum Standard {}
/// Coercion of behavior types and type parameters.
pub struct Coerce<T: ?Sized, From: ?Sized = Standard>(PhantomData<AtomicPtr<Box<From>>>, T);
impl<T, From: ?Sized> Coerce<T, From> {
#[must_use]
pub const fn wrap(val: T) -> Self {
Self(PhantomData, val)
pub const fn wrap(value: T) -> Self {
Self(PhantomData, value)
}
}
#[must_use]
pub const fn coerce<T, From: ?Sized>(val: T) -> Coerce<T, From> {
Coerce::wrap(val)
pub const fn coerce<T, From: ?Sized>(value: T) -> Coerce<T, From> {
Coerce::wrap(value)
}
impl<T, TI, SV, B1, B2> resolve::Type<TI, SV, B1> for Coerce<T, B2>
where
T: resolve::Type<TI, SV, B2> + ?Sized,
TI: ?Sized,
B1: ?Sized,
B2: ?Sized,
{
fn meta<'r, 'ti: 'r>(registry: &mut Registry<'r, SV>, type_info: &'ti TI) -> MetaType<'r, SV>
where
SV: 'r,
{
T::meta(registry, type_info)
}
}

View file

@ -84,12 +84,6 @@ where
field_path: Arc<FieldPath<'a>>,
}
impl<'r, 'a, Ctx: ?Sized, S> Executor<'r, 'a, Ctx, S> {
pub(crate) fn current_type_new(&self) -> &TypeType<'a, S> {
&self.current_type
}
}
/// Error type for errors that occur during query execution
///
/// All execution errors contain the source position in the query of the field
@ -1297,17 +1291,58 @@ impl<'r, S: 'r> Registry<'r, S> {
}
*/
/// Builds a [`ScalarMeta`] information for the specified [`?Sized`]
/// [`graphql::Type`].
/// Builds a [`ScalarMeta`] information for the specified non-[`Sized`]
/// [`graphql::Type`], and stores it in this [`Registry`].
///
/// # Idempotent
///
/// If this [`Registry`] contains a [`MetaType`] with such [`TypeName`]
/// already, then just returns it without doing anything.
///
/// [`graphql::Type`]: resolve::Type
pub fn build_scalar_type_unsized<T, TI>(&mut self, type_info: &TI) -> ScalarMeta<'r, S>
/// [`TypeName`]: resolve::TypeName
pub fn register_scalar_unsized<'ti, T, TI>(&mut self, type_info: &'ti TI) -> MetaType<'r, S>
where
T: resolve::TypeName<TI> + resolve::InputValueAsRef<S> + resolve::ScalarToken<S> + ?Sized,
TI: ?Sized,
'ti: 'r,
S: Clone,
{
// TODO: Allow using references.
ScalarMeta::new_unsized::<T, _>(T::type_name(type_info).to_owned())
// TODO: Use `drop` instead of `|_| {}` once Rust's inference becomes
// better for HRTB closures.
self.register_scalar_unsized_with::<T, TI, _>(type_info, |_| {})
}
/// Builds a [`ScalarMeta`] information for the specified non-[`Sized`]
/// [`graphql::Type`], allowing to `customize` the created [`ScalarMeta`],
/// and stores it in this [`Registry`].
///
/// # Idempotent
///
/// If this [`Registry`] contains a [`MetaType`] with such [`TypeName`]
/// already, then just returns it without doing anything.
///
/// [`graphql::Type`]: resolve::Type
/// [`TypeName`]: resolve::TypeName
pub fn register_scalar_unsized_with<'ti, T, TI, F>(
&mut self,
type_info: &'ti TI,
customize: F,
) -> MetaType<'r, S>
where
T: resolve::TypeName<TI> + resolve::InputValueAsRef<S> + resolve::ScalarToken<S> + ?Sized,
TI: ?Sized,
'ti: 'r,
F: FnOnce(&mut ScalarMeta<'r, S>),
S: Clone,
{
self.entry_type::<T, _>(type_info)
.or_insert_with(move || {
let mut scalar = ScalarMeta::new_unsized::<T, _>(T::type_name(type_info));
customize(&mut scalar);
scalar.into_meta()
})
.clone()
}
/// Creates a [`ListMeta`] type.
@ -1342,7 +1377,8 @@ impl<'r, S: 'r> Registry<'r, S> {
T: resolve::Type<Info, S> + ?Sized,
Info: ?Sized,
{
ListMeta::new(T::meta(self, info).as_type(), expected_size)
todo!()
//ListMeta::new(T::meta(self, info).as_type(), expected_size)
}
/// Creates a [`NullableMeta`] type.
@ -1359,13 +1395,13 @@ impl<'r, S: 'r> Registry<'r, S> {
/// [`graphql::Type`].
///
/// [`graphql::Type`]: resolve::Type
pub fn build_nullable_type_reworked<T, BH, TI>(&mut self, type_info: &TI) -> NullableMeta<'r>
pub fn wrap_nullable<'ti, T, TI>(&mut self, type_info: &'ti TI) -> MetaType<'r, S>
where
T: resolve::Type<TI, S, BH> + ?Sized,
BH: ?Sized,
T: resolve::Type<TI, S> + ?Sized,
TI: ?Sized,
'ti: 'r,
{
NullableMeta::new(T::meta(self, type_info).as_type())
NullableMeta::new(T::meta(self, type_info).into()).into_meta()
}
/// Creates an [`ObjectMeta`] type with the given `fields`.

View file

@ -6,9 +6,9 @@ use crate::{
};
pub trait Type<TypeInfo: ?Sized, ScalarValue, Behavior: ?Sized = behavior::Standard> {
fn meta<'r>(
fn meta<'r, 'ti: 'r>(
registry: &mut Registry<'r, ScalarValue>,
type_info: &TypeInfo,
type_info: &'ti TypeInfo,
) -> MetaType<'r, ScalarValue>
where
ScalarValue: 'r; // TODO: remove?

View file

@ -460,6 +460,29 @@ impl<'a, S> MetaType<'a, S> {
}
}
impl<'a, S> From<MetaType<'a, S>> for Type<'a> {
fn from(meta: MetaType<'a, S>) -> Self {
match meta {
MetaType::Scalar(ScalarMeta { name, .. })
| MetaType::Object(ObjectMeta { name, .. })
| MetaType::Enum(EnumMeta { name, .. })
| MetaType::Interface(InterfaceMeta { name, .. })
| MetaType::Union(UnionMeta { name, .. })
| MetaType::InputObject(InputObjectMeta { name, .. }) => Type::NonNullNamed(name),
MetaType::List(ListMeta {
of_type,
expected_size,
}) => Type::NonNullList(Box::new(of_type), expected_size),
MetaType::Nullable(NullableMeta { of_type }) => match of_type {
Type::NonNullNamed(inner) => Type::Named(inner),
Type::NonNullList(inner, expected_size) => Type::List(inner, expected_size),
t => t,
},
MetaType::Placeholder(PlaceholderMeta { of_type }) => of_type,
}
}
}
impl<'a, S> ScalarMeta<'a, S> {
/// Builds a new [`ScalarMeta`] type with the specified `name`.
pub fn new<T>(name: Cow<'a, str>) -> Self

View file

@ -15,7 +15,7 @@ where
TI: ?Sized,
BH: ?Sized,
{
fn meta<'r>(registry: &mut Registry<'r, SV>, type_info: &TI) -> MetaType<'r, SV>
fn meta<'r, 'ti: 'r>(registry: &mut Registry<'r, SV>, type_info: &'ti TI) -> MetaType<'r, SV>
where
SV: 'r,
{

View file

@ -13,7 +13,7 @@ where
TI: ?Sized,
BH: ?Sized,
{
fn meta<'r>(registry: &mut Registry<'r, SV>, type_info: &TI) -> MetaType<'r, SV>
fn meta<'r, 'ti: 'r>(registry: &mut Registry<'r, SV>, type_info: &'ti TI) -> MetaType<'r, SV>
where
SV: 'r,
{

View file

@ -6,6 +6,7 @@ use futures::future;
use crate::{
ast::{FromInputValue, InputValue, ToInputValue},
behavior,
executor::{ExecutionResult, Executor, Registry},
graphql, reflect, resolve,
schema::meta::MetaType,
@ -278,13 +279,11 @@ where
TI: ?Sized,
BH: ?Sized,
{
fn meta<'r>(registry: &mut Registry<'r, SV>, type_info: &TI) -> MetaType<'r, SV>
fn meta<'r, 'ti: 'r>(registry: &mut Registry<'r, SV>, type_info: &'ti TI) -> MetaType<'r, SV>
where
SV: 'r,
{
registry
.build_nullable_type_reworked::<T, BH, _>(type_info)
.into_meta()
registry.wrap_nullable::<behavior::Coerce<T, BH>, _>(type_info)
}
}

View file

@ -3,6 +3,7 @@
use futures::future;
use crate::{
behavior,
executor::{ExecutionResult, Executor, Registry},
graphql, reflect, resolve,
schema::meta::MetaType,
@ -15,13 +16,11 @@ where
TI: ?Sized,
BH: ?Sized,
{
fn meta<'r>(registry: &mut Registry<'r, SV>, type_info: &TI) -> MetaType<'r, SV>
fn meta<'r, 'ti: 'r>(registry: &mut Registry<'r, SV>, type_info: &'ti TI) -> MetaType<'r, SV>
where
SV: 'r,
{
registry
.build_nullable_type_reworked::<T, BH, _>(type_info)
.into_meta()
registry.wrap_nullable::<behavior::Coerce<T, BH>, _>(type_info)
}
}

View file

@ -15,7 +15,7 @@ where
TI: ?Sized,
BH: ?Sized,
{
fn meta<'r>(registry: &mut Registry<'r, SV>, type_info: &TI) -> MetaType<'r, SV>
fn meta<'r, 'ti: 'r>(registry: &mut Registry<'r, SV>, type_info: &'ti TI) -> MetaType<'r, SV>
where
SV: 'r,
{

View file

@ -15,7 +15,7 @@ where
TI: ?Sized,
BH: ?Sized,
{
fn meta<'r>(registry: &mut Registry<'r, SV>, type_info: &TI) -> MetaType<'r, SV>
fn meta<'r, 'ti: 'r>(registry: &mut Registry<'r, SV>, type_info: &'ti TI) -> MetaType<'r, SV>
where
SV: 'r,
{

View file

@ -15,7 +15,7 @@ where
TI: ?Sized,
BH: ?Sized,
{
fn meta<'r>(registry: &mut Registry<'r, SV>, type_info: &TI) -> MetaType<'r, SV>
fn meta<'r, 'ti: 'r>(registry: &mut Registry<'r, SV>, type_info: &'ti TI) -> MetaType<'r, SV>
where
SV: 'r,
{

View file

@ -14,17 +14,11 @@ use crate::{
};
impl<TI: ?Sized, SV: ScalarValue> resolve::Type<TI, SV> for str {
fn meta<'r>(registry: &mut Registry<'r, SV>, type_info: &TI) -> MetaType<'r, SV>
fn meta<'r, 'ti: 'r>(registry: &mut Registry<'r, SV>, type_info: &'ti TI) -> MetaType<'r, SV>
where
SV: 'r,
{
let meta = registry
.build_scalar_type_unsized::<Self, _>(type_info)
.into_meta();
registry
.entry_type::<Self, _>(type_info)
.or_insert(meta)
.clone()
registry.register_scalar_unsized::<Self, _>(type_info)
}
}
@ -75,6 +69,8 @@ where
SV: From<String>,
{
fn to_input_value(&self) -> graphql::InputValue<SV> {
// TODO: Remove redundant `.to_owned()` allocation by allowing
// `ScalarValue` creation from reference?
graphql::InputValue::scalar(self.to_owned())
}
}