Bikeshed reflection, vol.1

This commit is contained in:
tyranron 2022-05-31 00:29:14 +02:00
parent b1be8f1d29
commit 22f3f1887e
No known key found for this signature in database
GPG key ID: 762E144FB230A4F0
15 changed files with 267 additions and 137 deletions

View file

@ -44,10 +44,6 @@ pub trait BaseType<S> {
const NAME: Type;
}
impl<'a, S, T: BaseType<S> + ?Sized> BaseType<S> for &'a T {
const NAME: Type = T::NAME;
}
impl<'ctx, S, T> BaseType<S> for (&'ctx T::Context, T)
where
S: ScalarValue,
@ -56,42 +52,6 @@ where
const NAME: Type = T::NAME;
}
impl<S, T: BaseType<S>> BaseType<S> for Option<T> {
const NAME: Type = T::NAME;
}
impl<S, T: BaseType<S>> BaseType<S> for Nullable<T> {
const NAME: Type = T::NAME;
}
impl<S, T: BaseType<S>, E> BaseType<S> for Result<T, E> {
const NAME: Type = T::NAME;
}
impl<S, T: BaseType<S>> BaseType<S> for Vec<T> {
const NAME: Type = T::NAME;
}
impl<S, T: BaseType<S>> BaseType<S> for [T] {
const NAME: Type = T::NAME;
}
impl<S, T: BaseType<S>, const N: usize> BaseType<S> for [T; N] {
const NAME: Type = T::NAME;
}
impl<S, T: BaseType<S> + ?Sized> BaseType<S> for Box<T> {
const NAME: Type = T::NAME;
}
impl<S, T: BaseType<S> + ?Sized> BaseType<S> for Arc<T> {
const NAME: Type = T::NAME;
}
impl<S, T: BaseType<S> + ?Sized> BaseType<S> for Rc<T> {
const NAME: Type = T::NAME;
}
/// [Sub-types][2] of a [GraphQL object][1].
///
/// This trait is transparent to [`Option`], [`Vec`] and other containers.
@ -105,10 +65,6 @@ pub trait BaseSubTypes<S> {
const NAMES: Types;
}
impl<'a, S, T: BaseSubTypes<S> + ?Sized> BaseSubTypes<S> for &'a T {
const NAMES: Types = T::NAMES;
}
impl<'ctx, S, T> BaseSubTypes<S> for (&'ctx T::Context, T)
where
S: ScalarValue,
@ -117,42 +73,6 @@ where
const NAMES: Types = T::NAMES;
}
impl<S, T: BaseSubTypes<S>> BaseSubTypes<S> for Option<T> {
const NAMES: Types = T::NAMES;
}
impl<S, T: BaseSubTypes<S>> BaseSubTypes<S> for Nullable<T> {
const NAMES: Types = T::NAMES;
}
impl<S, T: BaseSubTypes<S>, E> BaseSubTypes<S> for Result<T, E> {
const NAMES: Types = T::NAMES;
}
impl<S, T: BaseSubTypes<S>> BaseSubTypes<S> for Vec<T> {
const NAMES: Types = T::NAMES;
}
impl<S, T: BaseSubTypes<S>> BaseSubTypes<S> for [T] {
const NAMES: Types = T::NAMES;
}
impl<S, T: BaseSubTypes<S>, const N: usize> BaseSubTypes<S> for [T; N] {
const NAMES: Types = T::NAMES;
}
impl<S, T: BaseSubTypes<S> + ?Sized> BaseSubTypes<S> for Box<T> {
const NAMES: Types = T::NAMES;
}
impl<S, T: BaseSubTypes<S> + ?Sized> BaseSubTypes<S> for Arc<T> {
const NAMES: Types = T::NAMES;
}
impl<S, T: BaseSubTypes<S> + ?Sized> BaseSubTypes<S> for Rc<T> {
const NAMES: Types = T::NAMES;
}
/// Alias for a value of a [`WrappedType`] (composed GraphQL type).
pub type WrappedValue = u128;
@ -163,7 +83,7 @@ pub type WrappedValue = u128;
/// because of the [wrapping types][2]. To work around this we use a
/// [`WrappedValue`] which is represented via [`u128`] number in the following
/// encoding:
/// - In base case of non-nullable [object][1] [`VALUE`] is `1`.
/// - In base case of non-nullable singular [object][1] [`VALUE`] is `1`.
/// - To represent nullability we "append" `2` to the [`VALUE`], so
/// [`Option`]`<`[object][1]`>` has [`VALUE`] of `12`.
/// - To represent list we "append" `3` to the [`VALUE`], so
@ -213,44 +133,18 @@ where
const VALUE: u128 = T::VALUE;
}
impl<S, T: WrappedType<S>> WrappedType<S> for Option<T> {
const VALUE: u128 = T::VALUE * 10 + 2;
}
pub mod wrap {
use super::WrappedValue;
impl<S, T: WrappedType<S>> WrappedType<S> for Nullable<T> {
const VALUE: u128 = T::VALUE * 10 + 2;
}
pub const SINGULAR: WrappedValue = 1;
impl<S, T: WrappedType<S>, E> WrappedType<S> for Result<T, E> {
const VALUE: u128 = T::VALUE;
}
pub const fn nullable(val: WrappedValue) -> WrappedValue {
val * 10 + 2
}
impl<S, T: WrappedType<S>> WrappedType<S> for Vec<T> {
const VALUE: u128 = T::VALUE * 10 + 3;
}
impl<S, T: WrappedType<S>> WrappedType<S> for [T] {
const VALUE: u128 = T::VALUE * 10 + 3;
}
impl<S, T: WrappedType<S>, const N: usize> WrappedType<S> for [T; N] {
const VALUE: u128 = T::VALUE * 10 + 3;
}
impl<'a, S, T: WrappedType<S> + ?Sized> WrappedType<S> for &'a T {
const VALUE: u128 = T::VALUE;
}
impl<S, T: WrappedType<S> + ?Sized> WrappedType<S> for Box<T> {
const VALUE: u128 = T::VALUE;
}
impl<S, T: WrappedType<S> + ?Sized> WrappedType<S> for Arc<T> {
const VALUE: u128 = T::VALUE;
}
impl<S, T: WrappedType<S> + ?Sized> WrappedType<S> for Rc<T> {
const VALUE: u128 = T::VALUE;
pub const fn list(val: WrappedValue) -> WrappedValue {
val * 10 + 3
}
}
/// Alias for a [GraphQL object][1] or [interface][2] [field argument][3] name.

View file

@ -6,8 +6,8 @@ use crate::{
graphql,
meta::MetaType,
parser::{ParseError, ScalarToken},
resolve, Arguments, BoxFuture, DefaultScalarValue, ExecutionResult, Executor, IntoFieldError,
Registry, Selection,
reflect, resolve, Arguments, BoxFuture, DefaultScalarValue, ExecutionResult, Executor,
IntoFieldError, Registry, Selection,
};
impl<T, Info, S> resolve::Type<Info, S> for Arc<T>
@ -247,3 +247,24 @@ where
T::assert_union()
}
}
impl<T, S> reflect::BaseType<S> for Arc<T>
where
T: reflect::BaseType<S> + ?Sized,
{
const NAME: reflect::Type = T::NAME;
}
impl<T, S> reflect::BaseSubTypes<S> for Arc<T>
where
T: reflect::BaseSubTypes<S> + ?Sized,
{
const NAMES: reflect::Types = T::NAMES;
}
impl<T, S> reflect::WrappedType<S> for Arc<T>
where
T: reflect::WrappedType<S> + ?Sized,
{
const VALUE: reflect::WrappedValue = T::VALUE;
}

View file

@ -4,7 +4,7 @@
use crate::{
executor::{ExecutionResult, Executor, Registry},
graphql, resolve,
graphql, reflect, resolve,
schema::meta::MetaType,
BoxFuture, Selection,
};
@ -81,3 +81,24 @@ where
T::assert_output_type()
}
}
impl<T, S, const N: usize> reflect::BaseType<S> for [T; N]
where
T: reflect::BaseType<S>,
{
const NAME: reflect::Type = T::NAME;
}
impl<T, S, const N: usize> reflect::BaseSubTypes<S> for [T; N]
where
T: reflect::BaseSubTypes<S>,
{
const NAMES: reflect::Types = T::NAMES;
}
impl<T, S, const N: usize> reflect::WrappedType<S> for [T; N]
where
T: reflect::WrappedType<S>,
{
const VALUE: reflect::WrappedValue = reflect::wrap::list(T::VALUE);
}

View file

@ -4,8 +4,8 @@ use crate::{
graphql,
meta::MetaType,
parser::{ParseError, ScalarToken},
resolve, Arguments, BoxFuture, DefaultScalarValue, ExecutionResult, Executor, IntoFieldError,
Registry, Selection,
reflect, resolve, Arguments, BoxFuture, DefaultScalarValue, ExecutionResult, Executor,
IntoFieldError, Registry, Selection,
};
impl<T, Info, S> resolve::Type<Info, S> for Box<T>
@ -245,3 +245,24 @@ where
T::assert_union()
}
}
impl<T, S> reflect::BaseType<S> for Box<T>
where
T: reflect::BaseType<S> + ?Sized,
{
const NAME: reflect::Type = T::NAME;
}
impl<T, S> reflect::BaseSubTypes<S> for Box<T>
where
T: reflect::BaseSubTypes<S> + ?Sized,
{
const NAMES: reflect::Types = T::NAMES;
}
impl<T, S> reflect::WrappedType<S> for Box<T>
where
T: reflect::WrappedType<S> + ?Sized,
{
const VALUE: reflect::WrappedValue = T::VALUE;
}

View file

@ -7,6 +7,7 @@ mod option;
pub mod rc;
pub mod r#ref;
mod ref_mut;
mod result;
mod slice;
mod r#str;
mod vec;

View file

@ -7,7 +7,7 @@ use futures::future;
use crate::{
ast::{FromInputValue, InputValue, ToInputValue},
executor::{ExecutionResult, Executor, Registry},
graphql, resolve,
graphql, reflect, resolve,
schema::meta::MetaType,
types::{
async_await::GraphQLValueAsync,
@ -361,6 +361,29 @@ where
}
}
impl<T, S> reflect::BaseType<S> for Nullable<T>
where
T: reflect::BaseType<S>,
{
const NAME: reflect::Type = T::NAME;
}
impl<T, S> reflect::BaseSubTypes<S> for Nullable<T>
where
T: reflect::BaseSubTypes<S>,
{
const NAMES: reflect::Types = T::NAMES;
}
impl<T, S> reflect::WrappedType<S> for Nullable<T>
where
T: reflect::WrappedType<S>,
{
const VALUE: reflect::WrappedValue = reflect::wrap::nullable(T::VALUE);
}
////////////////////////////////////////////////////////////////////////////////
impl<S, T> GraphQLType<S> for Nullable<T>
where
T: GraphQLType<S>,

View file

@ -4,7 +4,7 @@ use futures::future;
use crate::{
executor::{ExecutionResult, Executor, Registry},
graphql, resolve,
graphql, reflect, resolve,
schema::meta::MetaType,
BoxFuture, Selection,
};
@ -93,3 +93,24 @@ where
T::assert_output_type()
}
}
impl<T, S> reflect::BaseType<S> for Option<T>
where
T: reflect::BaseType<S>,
{
const NAME: reflect::Type = T::NAME;
}
impl<T, S> reflect::BaseSubTypes<S> for Option<T>
where
T: reflect::BaseSubTypes<S>,
{
const NAMES: reflect::Types = T::NAMES;
}
impl<T, S> reflect::WrappedType<S> for Option<T>
where
T: reflect::WrappedType<S>,
{
const VALUE: reflect::WrappedValue = reflect::wrap::nullable(T::VALUE);
}

View file

@ -6,8 +6,8 @@ use crate::{
graphql,
meta::MetaType,
parser::{ParseError, ScalarToken},
resolve, Arguments, BoxFuture, DefaultScalarValue, ExecutionResult, Executor, IntoFieldError,
Registry, Selection,
reflect, resolve, Arguments, BoxFuture, DefaultScalarValue, ExecutionResult, Executor,
IntoFieldError, Registry, Selection,
};
impl<T, Info, S> resolve::Type<Info, S> for Rc<T>
@ -247,3 +247,24 @@ where
T::assert_union()
}
}
impl<T, S> reflect::BaseType<S> for Rc<T>
where
T: reflect::BaseType<S> + ?Sized,
{
const NAME: reflect::Type = T::NAME;
}
impl<T, S> reflect::BaseSubTypes<S> for Rc<T>
where
T: reflect::BaseSubTypes<S> + ?Sized,
{
const NAMES: reflect::Types = T::NAMES;
}
impl<T, S> reflect::WrappedType<S> for Rc<T>
where
T: reflect::WrappedType<S> + ?Sized,
{
const VALUE: reflect::WrappedValue = T::VALUE;
}

View file

@ -6,8 +6,8 @@ use crate::{
graphql,
meta::MetaType,
parser::{ParseError, ScalarToken},
resolve, Arguments, BoxFuture, DefaultScalarValue, ExecutionResult, Executor, IntoFieldError,
Registry, Selection,
reflect, resolve, Arguments, BoxFuture, DefaultScalarValue, ExecutionResult, Executor,
IntoFieldError, Registry, Selection,
};
impl<'me, T, Info, S> resolve::Type<Info, S> for &'me T
@ -233,3 +233,24 @@ where
T::assert_union()
}
}
impl<'me, T, S> reflect::BaseType<S> for &'me T
where
T: reflect::BaseType<S> + ?Sized,
{
const NAME: reflect::Type = T::NAME;
}
impl<'me, T, S> reflect::BaseSubTypes<S> for &'me T
where
T: reflect::BaseSubTypes<S> + ?Sized,
{
const NAMES: reflect::Types = T::NAMES;
}
impl<'me, T, S> reflect::WrappedType<S> for &'me T
where
T: reflect::WrappedType<S> + ?Sized,
{
const VALUE: reflect::WrappedValue = T::VALUE;
}

View file

@ -6,7 +6,7 @@ use crate::{
graphql,
meta::MetaType,
parser::{ParseError, ScalarToken},
resolve, Arguments, BoxFuture, ExecutionResult, Executor, Registry, Selection,
reflect, resolve, Arguments, BoxFuture, ExecutionResult, Executor, Registry, Selection,
};
impl<'me, T, Info, S> resolve::Type<Info, S> for &'me mut T
@ -204,3 +204,24 @@ where
T::assert_union()
}
}
impl<'me, T, S> reflect::BaseType<S> for &'me mut T
where
T: reflect::BaseType<S> + ?Sized,
{
const NAME: reflect::Type = T::NAME;
}
impl<'me, T, S> reflect::BaseSubTypes<S> for &'me mut T
where
T: reflect::BaseSubTypes<S> + ?Sized,
{
const NAMES: reflect::Types = T::NAMES;
}
impl<'me, T, S> reflect::WrappedType<S> for &'me mut T
where
T: reflect::WrappedType<S> + ?Sized,
{
const VALUE: reflect::WrappedValue = T::VALUE;
}

View file

@ -0,0 +1,24 @@
//! GraphQL implementation for [`Result`].
use crate::reflect;
impl<T, E, S> reflect::BaseType<S> for Result<T, E>
where
T: reflect::BaseType<S>,
{
const NAME: reflect::Type = T::NAME;
}
impl<T, E, S> reflect::BaseSubTypes<S> for Result<T, E>
where
T: reflect::BaseSubTypes<S>,
{
const NAMES: reflect::Types = T::NAMES;
}
impl<T, E, S> reflect::WrappedType<S> for Result<T, E>
where
T: reflect::WrappedType<S>,
{
const VALUE: reflect::WrappedValue = T::VALUE;
}

View file

@ -4,7 +4,7 @@
use crate::{
executor::{ExecutionResult, Executor, Registry},
graphql, resolve,
graphql, reflect, resolve,
schema::meta::MetaType,
BoxFuture, Selection,
};
@ -79,3 +79,24 @@ where
T::assert_output_type()
}
}
impl<T, S> reflect::BaseType<S> for [T]
where
T: reflect::BaseType<S>,
{
const NAME: reflect::Type = T::NAME;
}
impl<T, S> reflect::BaseSubTypes<S> for [T]
where
T: reflect::BaseSubTypes<S>,
{
const NAMES: reflect::Types = T::NAMES;
}
impl<T, S> reflect::WrappedType<S> for [T]
where
T: reflect::WrappedType<S>,
{
const VALUE: reflect::WrappedValue = reflect::wrap::list(T::VALUE);
}

View file

@ -7,10 +7,10 @@ use std::{rc::Rc, sync::Arc};
use futures::future;
use crate::{
graphql, reflect,
graphql,
meta::MetaType,
parser::{ParseError, ScalarToken},
resolve, BoxFuture, ExecutionResult, Executor, Registry, ScalarValue, Selection,
reflect, resolve, BoxFuture, ExecutionResult, Executor, Registry, ScalarValue, Selection,
};
impl<Info: ?Sized, S: ScalarValue> resolve::Type<Info, S> for str {
@ -129,5 +129,5 @@ impl<S> reflect::BaseSubTypes<S> for str {
}
impl<S> reflect::WrappedType<S> for str {
const VALUE: reflect::WrappedValue = 1;
const VALUE: reflect::WrappedValue = reflect::wrap::SINGULAR;
}

View file

@ -2,7 +2,7 @@
use crate::{
executor::{ExecutionResult, Executor, Registry},
graphql, resolve,
graphql, reflect, resolve,
schema::meta::MetaType,
BoxFuture, Selection,
};
@ -77,3 +77,24 @@ where
T::assert_output_type()
}
}
impl<T, S> reflect::BaseType<S> for Vec<T>
where
T: reflect::BaseType<S>,
{
const NAME: reflect::Type = T::NAME;
}
impl<T, S> reflect::BaseSubTypes<S> for Vec<T>
where
T: reflect::BaseSubTypes<S>,
{
const NAMES: reflect::Types = T::NAMES;
}
impl<T, S> reflect::WrappedType<S> for Vec<T>
where
T: reflect::WrappedType<S>,
{
const VALUE: reflect::WrappedValue = reflect::wrap::list(T::VALUE);
}

View file

@ -471,15 +471,13 @@ impl Definition {
let (info, generics) = self.mix_info(generics);
let (impl_gens, _, where_clause) = generics.split_for_impl();
let name = &self.name;
quote! {
#[automatically_derived]
impl#impl_gens ::juniper::resolve::TypeName<#info> for #ty
#where_clause
{
fn type_name(_: &#info) -> &'static str {
#name
<Self as ::juniper::reflect::BaseType<()>>::NAME
}
}
}
@ -783,7 +781,8 @@ impl Definition {
impl#impl_gens ::juniper::reflect::WrappedType<#scalar> for #ty
#where_clause
{
const VALUE: ::juniper::reflect::WrappedValue = 1;
const VALUE: ::juniper::reflect::WrappedValue =
::juniper::reflect::wrap::SINGULAR;
}
}
}