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

View file

@ -6,8 +6,8 @@ use crate::{
graphql, graphql,
meta::MetaType, meta::MetaType,
parser::{ParseError, ScalarToken}, parser::{ParseError, ScalarToken},
resolve, Arguments, BoxFuture, DefaultScalarValue, ExecutionResult, Executor, IntoFieldError, reflect, resolve, Arguments, BoxFuture, DefaultScalarValue, ExecutionResult, Executor,
Registry, Selection, IntoFieldError, Registry, Selection,
}; };
impl<T, Info, S> resolve::Type<Info, S> for Arc<T> impl<T, Info, S> resolve::Type<Info, S> for Arc<T>
@ -247,3 +247,24 @@ where
T::assert_union() 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::{ use crate::{
executor::{ExecutionResult, Executor, Registry}, executor::{ExecutionResult, Executor, Registry},
graphql, resolve, graphql, reflect, resolve,
schema::meta::MetaType, schema::meta::MetaType,
BoxFuture, Selection, BoxFuture, Selection,
}; };
@ -81,3 +81,24 @@ where
T::assert_output_type() 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, graphql,
meta::MetaType, meta::MetaType,
parser::{ParseError, ScalarToken}, parser::{ParseError, ScalarToken},
resolve, Arguments, BoxFuture, DefaultScalarValue, ExecutionResult, Executor, IntoFieldError, reflect, resolve, Arguments, BoxFuture, DefaultScalarValue, ExecutionResult, Executor,
Registry, Selection, IntoFieldError, Registry, Selection,
}; };
impl<T, Info, S> resolve::Type<Info, S> for Box<T> impl<T, Info, S> resolve::Type<Info, S> for Box<T>
@ -245,3 +245,24 @@ where
T::assert_union() 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 rc;
pub mod r#ref; pub mod r#ref;
mod ref_mut; mod ref_mut;
mod result;
mod slice; mod slice;
mod r#str; mod r#str;
mod vec; mod vec;

View file

@ -7,7 +7,7 @@ use futures::future;
use crate::{ use crate::{
ast::{FromInputValue, InputValue, ToInputValue}, ast::{FromInputValue, InputValue, ToInputValue},
executor::{ExecutionResult, Executor, Registry}, executor::{ExecutionResult, Executor, Registry},
graphql, resolve, graphql, reflect, resolve,
schema::meta::MetaType, schema::meta::MetaType,
types::{ types::{
async_await::GraphQLValueAsync, 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> impl<S, T> GraphQLType<S> for Nullable<T>
where where
T: GraphQLType<S>, T: GraphQLType<S>,

View file

@ -4,7 +4,7 @@ use futures::future;
use crate::{ use crate::{
executor::{ExecutionResult, Executor, Registry}, executor::{ExecutionResult, Executor, Registry},
graphql, resolve, graphql, reflect, resolve,
schema::meta::MetaType, schema::meta::MetaType,
BoxFuture, Selection, BoxFuture, Selection,
}; };
@ -93,3 +93,24 @@ where
T::assert_output_type() 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, graphql,
meta::MetaType, meta::MetaType,
parser::{ParseError, ScalarToken}, parser::{ParseError, ScalarToken},
resolve, Arguments, BoxFuture, DefaultScalarValue, ExecutionResult, Executor, IntoFieldError, reflect, resolve, Arguments, BoxFuture, DefaultScalarValue, ExecutionResult, Executor,
Registry, Selection, IntoFieldError, Registry, Selection,
}; };
impl<T, Info, S> resolve::Type<Info, S> for Rc<T> impl<T, Info, S> resolve::Type<Info, S> for Rc<T>
@ -247,3 +247,24 @@ where
T::assert_union() 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, graphql,
meta::MetaType, meta::MetaType,
parser::{ParseError, ScalarToken}, parser::{ParseError, ScalarToken},
resolve, Arguments, BoxFuture, DefaultScalarValue, ExecutionResult, Executor, IntoFieldError, reflect, resolve, Arguments, BoxFuture, DefaultScalarValue, ExecutionResult, Executor,
Registry, Selection, IntoFieldError, Registry, Selection,
}; };
impl<'me, T, Info, S> resolve::Type<Info, S> for &'me T impl<'me, T, Info, S> resolve::Type<Info, S> for &'me T
@ -233,3 +233,24 @@ where
T::assert_union() 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, graphql,
meta::MetaType, meta::MetaType,
parser::{ParseError, ScalarToken}, 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 impl<'me, T, Info, S> resolve::Type<Info, S> for &'me mut T
@ -204,3 +204,24 @@ where
T::assert_union() 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::{ use crate::{
executor::{ExecutionResult, Executor, Registry}, executor::{ExecutionResult, Executor, Registry},
graphql, resolve, graphql, reflect, resolve,
schema::meta::MetaType, schema::meta::MetaType,
BoxFuture, Selection, BoxFuture, Selection,
}; };
@ -79,3 +79,24 @@ where
T::assert_output_type() 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 futures::future;
use crate::{ use crate::{
graphql, reflect, graphql,
meta::MetaType, meta::MetaType,
parser::{ParseError, ScalarToken}, 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 { 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 { 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::{ use crate::{
executor::{ExecutionResult, Executor, Registry}, executor::{ExecutionResult, Executor, Registry},
graphql, resolve, graphql, reflect, resolve,
schema::meta::MetaType, schema::meta::MetaType,
BoxFuture, Selection, BoxFuture, Selection,
}; };
@ -77,3 +77,24 @@ where
T::assert_output_type() 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 (info, generics) = self.mix_info(generics);
let (impl_gens, _, where_clause) = generics.split_for_impl(); let (impl_gens, _, where_clause) = generics.split_for_impl();
let name = &self.name;
quote! { quote! {
#[automatically_derived] #[automatically_derived]
impl#impl_gens ::juniper::resolve::TypeName<#info> for #ty impl#impl_gens ::juniper::resolve::TypeName<#info> for #ty
#where_clause #where_clause
{ {
fn type_name(_: &#info) -> &'static str { 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 impl#impl_gens ::juniper::reflect::WrappedType<#scalar> for #ty
#where_clause #where_clause
{ {
const VALUE: ::juniper::reflect::WrappedValue = 1; const VALUE: ::juniper::reflect::WrappedValue =
::juniper::reflect::wrap::SINGULAR;
} }
} }
} }