Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rework core traits #1072

Draft
wants to merge 68 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
56a68a9
Bootstrap, vol.1
tyranron Apr 19, 2022
4ef63e0
Bootstrap, vol.2
tyranron Apr 19, 2022
d005499
Merge branch 'master' into rework-core-traits
tyranron Apr 22, 2022
2d1e5d3
Impl some basic types
tyranron Apr 22, 2022
c8759cd
Impl basic types, vol.2
tyranron Apr 25, 2022
64cf7ad
Impl basic types, vol.3
tyranron May 5, 2022
72cd4be
Merge branch 'master' into rework-core-traits
tyranron May 10, 2022
bde5b83
Upd
tyranron May 11, 2022
ffc42b1
Merge branch 'master' into rework-core-traits
tyranron May 12, 2022
912d31f
Poking with parsing input
tyranron May 12, 2022
e381602
Merge branch 'master' into rework-core-traits
tyranron May 17, 2022
5a3bd6c
Pave way to parse `?Sized` types from `InputValue`
tyranron May 17, 2022
21c7a3a
Bootstrap codegen for scalars
tyranron May 17, 2022
8ea231f
Building up codegen for scalars, vol.2
tyranron May 19, 2022
224b049
Merge branch 'master' into rework-core-traits
tyranron May 27, 2022
b381c69
Improve and polish codegen for scalars
tyranron May 27, 2022
b1be8f1
Improve codegen for scalars, vol.2
tyranron May 30, 2022
22f3f18
Bikeshed reflection, vol.1
tyranron May 30, 2022
113b112
Impl codegen for scalars (`resolve::Value` trait), vol.3
tyranron May 31, 2022
740aa90
Impl codegen for scalars (`resolve::ValueAsync` trait), vol.4
tyranron Jun 1, 2022
97d2da5
Impl codegen for scalars (`resolve::ToInputValue` trait), vol.5
tyranron Jun 1, 2022
8235ac2
Reworking base traits, vol.1 [skip ci]
tyranron Jun 6, 2022
97c88d2
Reworking base traits, vol.2
tyranron Jun 7, 2022
b716a45
Refactor `input_value!` macro position [skip ci]
tyranron Jun 7, 2022
b28acbd
Refactor `value!` macro position [skip ci]
tyranron Jun 7, 2022
e347f25
Refactor `vars!` macro position [skip ci]
tyranron Jun 8, 2022
5a62ddf
Restore old reflection impls
tyranron Jun 8, 2022
017e87c
Reimpl renewed traits machinery for `Box` [skip ci]
tyranron Jun 8, 2022
5ab398e
Re-impl renewed traits machinery for other pointer types
tyranron Jun 9, 2022
be010e8
Re-impl renewed traits machinery for container types
tyranron Jun 9, 2022
88046e3
Re-implement `str`, vol.1 [skip ci]
tyranron Jun 9, 2022
067b1e5
Re-implement `str`, vol.2 [skip ci]
tyranron Jun 13, 2022
25404eb
Rework meta creation [skip ci]
tyranron Jun 17, 2022
f2718cc
Impl macro for scalars, vol.1 [skip ci]
tyranron Jun 17, 2022
a05a009
Impl macro for scalars, vol.2 [skip ci]
tyranron Jun 17, 2022
679c1c1
Impl macro for scalars, vol.3 [skip ci]
tyranron Jun 17, 2022
1aafd3d
Impl macro for scalars, vol.4 [skip ci]
tyranron Jun 19, 2022
4d7770d
Impl macro for scalars, vol.5 [skip ci]
tyranron Jun 19, 2022
66c11ec
Impl macro for scalars, vol.6 [skip ci]
tyranron Jun 20, 2022
2d89de3
Impl new machinery for `Vec` [skip ci]
tyranron Jun 20, 2022
d648181
Fix `reflect` impls for `Result`
tyranron Jun 21, 2022
17af7c5
Impl new machinery for array
tyranron Jun 21, 2022
4a6b3ab
Impl new machinery for slice [skip ci]
tyranron Jun 21, 2022
3cfc4eb
Impl new machinery for `Cow` [skip ci]
tyranron Jun 21, 2022
07ed785
Move tests for containers [skip ci]
tyranron Jun 21, 2022
42e2780
Fix tests
tyranron Jun 23, 2022
23e0195
Impl `reflect` traits for objects and interfaces [skip ci]
tyranron Jun 23, 2022
1819ab6
Impl `reflect` traits for objects and interfaces fields, vol.1 [skip ci]
tyranron Jun 23, 2022
2e2d365
Merge branch `master` into `rework-core-traits` [skip ci]
tyranron Jun 27, 2022
505e25c
Temporary disable new reflection for fields as it requires all leaf t…
tyranron Jun 27, 2022
48631e9
Impl `reflect` traits for enums
tyranron Jun 27, 2022
7364187
Impl `resolve::Value` and `resolve::ToInputValue` traits for enums [s…
tyranron Jun 27, 2022
98b282d
Impl `resolve::InputValue` trait for enums
tyranron Jun 27, 2022
4257e72
Impl `resolve::Type` trait for enums
tyranron Jun 27, 2022
fa03c7f
Impl `graphql::Enum` trait for enums [skip ci]
tyranron Jun 27, 2022
d8813af
Merge branch `master` into rework-core-traits [skip ci]
tyranron Aug 10, 2022
464ff10
Impl input objects, vol.1 [skip ci]
tyranron Aug 10, 2022
fea722b
Impl input objects, vol.2 [skip ci]
tyranron Aug 11, 2022
3725793
Some code style corrections [skip ci]
tyranron Aug 11, 2022
b3659b8
Impl objects, vol.1 [skip ci]
tyranron Aug 11, 2022
e6861bc
Merge branch 'master' into rework-core-traits [skip ci]
tyranron Aug 12, 2022
c75d33a
Impl field resolving, vol.1
tyranron Aug 29, 2022
d1f2173
Impl fields resolving, vol.2 [skip ci]
tyranron Aug 29, 2022
129ff55
Impl fields resolving, vol.3 [skip ci]
tyranron Sep 9, 2022
bf21986
Impl fields resolving, vol.4 [skip ci]
tyranron Sep 12, 2022
1ddf0bd
Impl hrtbifying
tyranron Sep 20, 2022
0b6544d
Merge branch 'master' into rework-core-traits
tyranron Sep 20, 2022
2d01486
Yay! Static fields, finally, minimally resolving [skip ci]
tyranron Sep 20, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 61 additions & 12 deletions juniper/src/ast.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{borrow::Cow, fmt, hash::Hash, slice, vec};
use std::{any::TypeId, borrow::Cow, convert::Into, fmt, hash::Hash, mem, slice, vec};

use indexmap::IndexMap;

Expand Down Expand Up @@ -256,30 +256,43 @@ impl<S> InputValue<S> {
Self::Variable(v.as_ref().into())
}

/// Construct a [`Spanning::unlocated`] list.
/// Constructs a [`Spanning::unlocated`] [`InputValue::List`].
///
/// Convenience function to make each [`InputValue`] in the input vector
/// not contain any location information. Can be used from [`ToInputValue`]
/// implementations, where no source code position information is available.
pub fn list(l: Vec<Self>) -> Self {
Self::List(l.into_iter().map(Spanning::unlocated).collect())
/// Convenience function to make each [`InputValue`] in the input `list` to
/// not contain any location information.
///
/// Intended for [`resolve::ToInputValue`] implementations, where no source
/// code position information is available.
///
/// [`resolve::ToInputValue`]: juniper::resolve::ToInputValue
pub fn list(list: impl IntoIterator<Item = Self>) -> Self {
Self::List(list.into_iter().map(Spanning::unlocated).collect())
}

/// Construct a located list.
pub fn parsed_list(l: Vec<Spanning<Self>>) -> Self {
Self::List(l)
}

/// Construct aa [`Spanning::unlocated`] object.
/// Construct a [`Spanning::unlocated`] [`InputValue::Onject`].
///
/// Similarly to [`InputValue::list()`] it makes each key and value in the
/// given `obj`ect to not contain any location information.
///
/// Similarly to [`InputValue::list`] it makes each key and value in the
/// given hash map not contain any location information.
pub fn object<K>(o: IndexMap<K, Self>) -> Self
/// Intended for [`resolve::ToInputValue`] implementations, where no source
/// code position information is available.
///
/// [`resolve::ToInputValue`]: juniper::resolve::ToInputValue
// TODO: Use `impl IntoIterator<Item = (K, Self)>` argument once feature
// `explicit_generic_args_with_impl_trait` hits stable:
// https://github.com/rust-lang/rust/issues/83701
pub fn object<K, O>(obj: O) -> Self
where
K: AsRef<str> + Eq + Hash,
O: IntoIterator<Item = (K, Self)>,
{
Self::Object(
o.into_iter()
obj.into_iter()
.map(|(k, v)| {
(
Spanning::unlocated(k.as_ref().into()),
Expand Down Expand Up @@ -459,6 +472,42 @@ impl<S> InputValue<S> {
_ => false,
}
}

/// Maps the [`ScalarValue`] type of this [`InputValue`] into the specified
/// one.
pub fn map_scalar_value<Into>(self) -> InputValue<Into>
where
S: ScalarValue,
Into: ScalarValue,
{
if TypeId::of::<Into>() == TypeId::of::<S>() {
// SAFETY: This is safe, because we're transmuting the value into
// itself, so no invariants may change and we're just
// satisfying the type checker.
// As `mem::transmute_copy` creates a copy of data, we need
// `mem::ManuallyDrop` here to omit double-free when
// `S: Drop`.
let val = mem::ManuallyDrop::new(self);
unsafe { mem::transmute_copy(&*val) }
} else {
match self {
Self::Null => InputValue::Null,
Self::Scalar(s) => InputValue::Scalar(s.into_another()),
Self::Enum(v) => InputValue::Enum(v),
Self::Variable(n) => InputValue::Variable(n),
Self::List(l) => InputValue::List(
l.into_iter()
.map(|i| i.map(InputValue::map_scalar_value))
.collect(),
),
Self::Object(o) => InputValue::Object(
o.into_iter()
.map(|(k, v)| (k, v.map(InputValue::map_scalar_value)))
.collect(),
),
}
}
}
}

impl<S: ScalarValue> fmt::Display for InputValue<S> {
Expand Down
130 changes: 130 additions & 0 deletions juniper/src/behavior.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
//! GraphQL types behavior machinery.

use std::{marker::PhantomData, sync::atomic::AtomicPtr};

use crate::{
graphql,
meta::MetaType,
parser::{ParseError, ScalarToken},
reflect, resolve, Registry,
};

/// Default standard behavior of GraphQL types implementation.
#[derive(Debug)]
pub enum Standard {}

/// Transparent wrapper allowing coercion of behavior types and type parameters.
#[repr(transparent)]
pub struct Coerce<T: ?Sized, To: ?Sized = Standard>(PhantomData<AtomicPtr<Box<To>>>, T);

impl<T, To: ?Sized> Coerce<T, To> {
/// Wraps the provided `value` into a [`Coerce`] wrapper.
#[must_use]
pub const fn wrap(value: T) -> Self {
Self(PhantomData, value)
}

/// Unwraps into the inner value.
#[must_use]
pub fn into_inner(self) -> T {
self.1
}
}

/// Wraps the provided `value` into a [`Coerce`] wrapper.
#[must_use]
pub const fn coerce<T, To: ?Sized>(value: T) -> Coerce<T, To> {
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)
}
}

impl<T, TI, B1, B2> resolve::TypeName<TI, B1> for Coerce<T, B2>
where
T: resolve::TypeName<TI, B2> + ?Sized,
TI: ?Sized,
B1: ?Sized,
B2: ?Sized,
{
fn type_name(type_info: &TI) -> &str {
T::type_name(type_info)
}
}

impl<'i, T, SV, B1, B2> resolve::InputValue<'i, SV, B1> for Coerce<T, B2>
where
T: resolve::InputValue<'i, SV, B2>,
SV: 'i,
B1: ?Sized,
B2: ?Sized,
{
type Error = T::Error;

fn try_from_input_value(v: &'i graphql::InputValue<SV>) -> Result<Self, Self::Error> {
T::try_from_input_value(v).map(Self::wrap)
}

fn try_from_implicit_null() -> Result<Self, Self::Error> {
T::try_from_implicit_null().map(Self::wrap)
}
}

impl<T, SV, B1, B2> resolve::ScalarToken<SV, B1> for Coerce<T, B2>
where
T: resolve::ScalarToken<SV, B2> + ?Sized,
B1: ?Sized,
B2: ?Sized,
{
fn parse_scalar_token(token: ScalarToken<'_>) -> Result<SV, ParseError> {
T::parse_scalar_token(token)
}
}

impl<T, B1, B2> reflect::BaseType<B1> for Coerce<T, B2>
where
T: reflect::BaseType<B2> + ?Sized,
B1: ?Sized,
B2: ?Sized,
{
const NAME: reflect::Type = T::NAME;
}

impl<T, B1, B2> reflect::BaseSubTypes<B1> for Coerce<T, B2>
where
T: reflect::BaseSubTypes<B2> + ?Sized,
B1: ?Sized,
B2: ?Sized,
{
const NAMES: reflect::Types = T::NAMES;
}

impl<T, B1, B2> reflect::WrappedType<B1> for Coerce<T, B2>
where
T: reflect::WrappedType<B2> + ?Sized,
B1: ?Sized,
B2: ?Sized,
{
const VALUE: reflect::WrappedValue = T::VALUE;
}

impl<T, B1, B2> reflect::Implements<B1> for Coerce<T, B2>
where
T: reflect::Implements<B2> + ?Sized,
B1: ?Sized,
B2: ?Sized,
{
const NAMES: reflect::Types = T::NAMES;
}
Loading