From 3cfc4eb0e4a4d2b905f31f4b78870fb1cc391211 Mon Sep 17 00:00:00 2001 From: tyranron Date: Tue, 21 Jun 2022 17:49:35 +0200 Subject: [PATCH] Impl new machinery for `Cow` [skip ci] --- juniper/src/types/arc.rs | 2 +- juniper/src/types/box.rs | 2 +- juniper/src/types/cow.rs | 291 +++++++++++++++++++++++++++++++++++++ juniper/src/types/mod.rs | 1 + juniper/src/types/rc.rs | 2 +- juniper/src/types/ref.rs | 8 +- juniper/src/types/slice.rs | 17 ++- juniper/src/types/str.rs | 37 ++++- 8 files changed, 351 insertions(+), 9 deletions(-) create mode 100644 juniper/src/types/cow.rs diff --git a/juniper/src/types/arc.rs b/juniper/src/types/arc.rs index db4c6cba..c49d9a45 100644 --- a/juniper/src/types/arc.rs +++ b/juniper/src/types/arc.rs @@ -178,7 +178,7 @@ where } } -impl<'i, T, SV, BH> resolve::InputValueAs<'i, Arc, SV, BH> for T +impl<'i, T, SV, BH> resolve::InputValueAs<'i, Arc, SV, BH> for T where T: resolve::InputValue<'i, SV, BH>, SV: 'i, diff --git a/juniper/src/types/box.rs b/juniper/src/types/box.rs index 845343d2..9724d307 100644 --- a/juniper/src/types/box.rs +++ b/juniper/src/types/box.rs @@ -176,7 +176,7 @@ where } } -impl<'i, T, SV, BH> resolve::InputValueAs<'i, Box, SV, BH> for T +impl<'i, T, SV, BH> resolve::InputValueAs<'i, Box, SV, BH> for T where T: resolve::InputValue<'i, SV, BH>, SV: 'i, diff --git a/juniper/src/types/cow.rs b/juniper/src/types/cow.rs new file mode 100644 index 00000000..9626a870 --- /dev/null +++ b/juniper/src/types/cow.rs @@ -0,0 +1,291 @@ +//! GraphQL implementation for [`Cow`]. + +use std::{borrow::Cow, ops::Deref}; + +use crate::{ + graphql, + meta::MetaType, + parser::{ParseError, ScalarToken}, + reflect, resolve, Arguments, BoxFuture, ExecutionResult, Executor, Registry, Selection, +}; + +impl<'me, T, TI, SV, BH> resolve::Type for Cow<'me, T> +where + T: resolve::Type + ToOwned + ?Sized + 'me, + TI: ?Sized, + BH: ?Sized, + Self: Deref, +{ + 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<'me, T, TI, BH> resolve::TypeName for Cow<'me, T> +where + T: resolve::TypeName + ToOwned + ?Sized + 'me, + TI: ?Sized, + BH: ?Sized, + Self: Deref, +{ + fn type_name(type_info: &TI) -> &str { + T::type_name(type_info) + } +} + +impl<'me, T, TI, BH> resolve::ConcreteTypeName for Cow<'me, T> +where + T: resolve::ConcreteTypeName + ToOwned + ?Sized + 'me, + TI: ?Sized, + BH: ?Sized, + Self: Deref, +{ + fn concrete_type_name<'i>(&self, type_info: &'i TI) -> &'i str { + (**self).concrete_type_name(type_info) + } +} + +impl<'me, T, TI, CX, SV, BH> resolve::Value for Cow<'me, T> +where + T: resolve::Value + ToOwned + ?Sized + 'me, + TI: ?Sized, + CX: ?Sized, + BH: ?Sized, + Self: Deref, +{ + fn resolve_value( + &self, + selection_set: Option<&[Selection<'_, SV>]>, + type_info: &TI, + executor: &Executor, + ) -> ExecutionResult { + (**self).resolve_value(selection_set, type_info, executor) + } +} + +impl<'me, T, TI, CX, SV, BH> resolve::ValueAsync for Cow<'me, T> +where + T: resolve::ValueAsync + ToOwned + ?Sized + 'me, + TI: ?Sized, + CX: ?Sized, + BH: ?Sized, + Self: Deref, +{ + fn resolve_value_async<'r>( + &'r self, + selection_set: Option<&'r [Selection<'_, SV>]>, + type_info: &'r TI, + executor: &'r Executor, + ) -> BoxFuture<'r, ExecutionResult> { + (**self).resolve_value_async(selection_set, type_info, executor) + } +} + +impl<'me, T, TI, CX, SV, BH> resolve::ConcreteValue for Cow<'me, T> +where + T: resolve::ConcreteValue + ToOwned + ?Sized + 'me, + TI: ?Sized, + CX: ?Sized, + BH: ?Sized, + Self: Deref, +{ + fn resolve_concrete_value( + &self, + type_name: &str, + selection_set: Option<&[Selection<'_, SV>]>, + type_info: &TI, + executor: &Executor, + ) -> ExecutionResult { + (**self).resolve_concrete_value(type_name, selection_set, type_info, executor) + } +} + +impl<'me, T, TI, CX, SV, BH> resolve::ConcreteValueAsync for Cow<'me, T> +where + T: resolve::ConcreteValueAsync + ToOwned + ?Sized + 'me, + TI: ?Sized, + CX: ?Sized, + BH: ?Sized, + Self: Deref, +{ + fn resolve_concrete_value_async<'r>( + &'r self, + type_name: &str, + selection_set: Option<&'r [Selection<'_, SV>]>, + type_info: &'r TI, + executor: &'r Executor, + ) -> BoxFuture<'r, ExecutionResult> { + (**self).resolve_concrete_value_async(type_name, selection_set, type_info, executor) + } +} + +impl<'me, T, TI, CX, SV, BH> resolve::Field for Cow<'me, T> +where + T: resolve::Field + ToOwned + ?Sized + 'me, + TI: ?Sized, + CX: ?Sized, + BH: ?Sized, + Self: Deref, +{ + fn resolve_field( + &self, + field_name: &str, + arguments: &Arguments, + type_info: &TI, + executor: &Executor, + ) -> ExecutionResult { + (**self).resolve_field(field_name, arguments, type_info, executor) + } +} + +impl<'me, T, TI, CX, SV, BH> resolve::FieldAsync for Cow<'me, T> +where + T: resolve::FieldAsync + ToOwned + ?Sized + 'me, + TI: ?Sized, + CX: ?Sized, + BH: ?Sized, + Self: Deref, +{ + fn resolve_field_async<'r>( + &'r self, + field_name: &'r str, + arguments: &'r Arguments, + type_info: &'r TI, + executor: &'r Executor, + ) -> BoxFuture<'r, ExecutionResult> { + (**self).resolve_field_async(field_name, arguments, type_info, executor) + } +} + +impl<'me, T, SV, BH> resolve::ToInputValue for Cow<'me, T> +where + T: resolve::ToInputValue + ToOwned + ?Sized + 'me, + BH: ?Sized, + Self: Deref, +{ + fn to_input_value(&self) -> graphql::InputValue { + (**self).to_input_value() + } +} + +impl<'me, 'i, T, SV, BH> resolve::InputValue<'i, SV, BH> for Cow<'me, T> +where + 'i: 'me, + T: resolve::InputValueAs<'i, Self, SV, BH> + ToOwned + ?Sized + 'me, + SV: 'i, + BH: ?Sized, + Self: Deref, +{ + type Error = T::Error; + + fn try_from_input_value(v: &'i graphql::InputValue) -> Result { + T::try_from_input_value(v) + } + + fn try_from_implicit_null() -> Result { + T::try_from_implicit_null() + } +} + +impl<'me, 'i, T, SV, BH> resolve::InputValueAs<'i, Cow<'me, Self>, SV, BH> for T +where + 'i: 'me, + T: resolve::InputValueAsRef + ToOwned + 'me, + SV: 'i, + BH: ?Sized, + Cow<'me, Self>: Deref, +{ + type Error = T::Error; + + fn try_from_input_value(v: &'i graphql::InputValue) -> Result, Self::Error> { + T::try_from_input_value(v).map(Cow::Borrowed) + } + + fn try_from_implicit_null() -> Result, Self::Error> { + T::try_from_implicit_null().map(Cow::Borrowed) + } +} + +impl<'me, T, SV, BH> resolve::ScalarToken for Cow<'me, T> +where + T: resolve::ScalarToken + ToOwned + ?Sized + 'me, + BH: ?Sized, + Self: Deref, +{ + fn parse_scalar_token(token: ScalarToken<'_>) -> Result> { + T::parse_scalar_token(token) + } +} + +impl<'me, 'i, T, TI, SV, BH> graphql::InputType<'i, TI, SV, BH> for Cow<'me, T> +where + 'i: 'me, + T: graphql::InputTypeAs<'i, Self, TI, SV, BH> + ToOwned + ?Sized + 'me, + TI: ?Sized, + SV: 'i, + BH: ?Sized, + Self: Deref, +{ + fn assert_input_type() { + T::assert_input_type() + } +} + +impl<'me, T, TI, CX, SV, BH> graphql::OutputType for Cow<'me, T> +where + T: graphql::OutputType + ToOwned + ?Sized + 'me, + TI: ?Sized, + CX: ?Sized, + BH: ?Sized, + Self: Deref, +{ + fn assert_output_type() { + T::assert_output_type() + } +} + +impl<'me, 'i, T, TI, CX, SV, BH> graphql::Scalar<'i, TI, CX, SV, BH> for Cow<'me, T> +where + 'i: 'me, + T: graphql::ScalarAs<'i, Self, TI, CX, SV, BH> + ToOwned + ?Sized + 'me, + TI: ?Sized, + CX: ?Sized, + SV: 'i, + BH: ?Sized, + + Self: Deref, +{ + fn assert_scalar() { + T::assert_scalar() + } +} + +impl<'me, T, BH> reflect::BaseType for Cow<'me, T> +where + T: reflect::BaseType + ToOwned + ?Sized + 'me, + BH: ?Sized, + Self: Deref, +{ + const NAME: reflect::Type = T::NAME; +} + +impl<'me, T, BH> reflect::BaseSubTypes for Cow<'me, T> +where + T: reflect::BaseSubTypes + ToOwned + ?Sized + 'me, + BH: ?Sized, + Self: Deref, +{ + const NAMES: reflect::Types = T::NAMES; +} + +impl<'me, T, BH> reflect::WrappedType for Cow<'me, T> +where + T: reflect::WrappedType + ToOwned + ?Sized + 'me, + BH: ?Sized, + Self: Deref, +{ + const VALUE: reflect::WrappedValue = T::VALUE; +} diff --git a/juniper/src/types/mod.rs b/juniper/src/types/mod.rs index 1fe0dfe2..fd5e0abb 100644 --- a/juniper/src/types/mod.rs +++ b/juniper/src/types/mod.rs @@ -1,6 +1,7 @@ mod arc; pub mod array; mod r#box; +mod cow; pub mod iter; mod nullable; mod option; diff --git a/juniper/src/types/rc.rs b/juniper/src/types/rc.rs index f886e910..8e00993d 100644 --- a/juniper/src/types/rc.rs +++ b/juniper/src/types/rc.rs @@ -178,7 +178,7 @@ where } } -impl<'i, T, SV, BH> resolve::InputValueAs<'i, Rc, SV, BH> for T +impl<'i, T, SV, BH> resolve::InputValueAs<'i, Rc, SV, BH> for T where T: resolve::InputValue<'i, SV, BH>, SV: 'i, diff --git a/juniper/src/types/ref.rs b/juniper/src/types/ref.rs index 867f4f48..805b1472 100644 --- a/juniper/src/types/ref.rs +++ b/juniper/src/types/ref.rs @@ -164,7 +164,7 @@ where impl<'me, 'i, T, SV, BH> resolve::InputValue<'i, SV, BH> for &'me T where 'i: 'me, - T: resolve::InputValueAs<'i, &'me T, SV, BH> + ?Sized, + T: resolve::InputValueAs<'i, Self, SV, BH> + ?Sized, SV: 'i, BH: ?Sized, { @@ -179,7 +179,7 @@ where } } -impl<'me, 'i, T, SV, BH> resolve::InputValueAs<'i, &'me T, SV, BH> for T +impl<'me, 'i, T, SV, BH> resolve::InputValueAs<'i, &'me Self, SV, BH> for T where 'i: 'me, T: resolve::InputValueAsRef + ?Sized, @@ -188,11 +188,11 @@ where { type Error = T::Error; - fn try_from_input_value(v: &'i graphql::InputValue) -> Result<&'me T, Self::Error> { + fn try_from_input_value(v: &'i graphql::InputValue) -> Result<&'me Self, Self::Error> { T::try_from_input_value(v) } - fn try_from_implicit_null() -> Result<&'me T, Self::Error> { + fn try_from_implicit_null() -> Result<&'me Self, Self::Error> { T::try_from_implicit_null() } } diff --git a/juniper/src/types/slice.rs b/juniper/src/types/slice.rs index 6eabb1fc..6a3f0124 100644 --- a/juniper/src/types/slice.rs +++ b/juniper/src/types/slice.rs @@ -2,7 +2,7 @@ //! //! [slice]: prim@slice -use std::{rc::Rc, sync::Arc}; +use std::{borrow::Cow, rc::Rc, sync::Arc}; use crate::{ behavior, @@ -78,6 +78,21 @@ where } } +impl<'me, 'i, T, SV, BH> resolve::InputValueAs<'i, Cow<'me, Self>, SV, BH> for [T] +where + Vec: resolve::InputValue<'i, SV, BH>, + SV: 'i, + BH: ?Sized, + Self: ToOwned, +{ + type Error = as resolve::InputValue<'i, SV, BH>>::Error; + + fn try_from_input_value(v: &'i graphql::InputValue) -> Result, Self::Error> { + as resolve::InputValue<'i, SV, BH>>::try_from_input_value(v) + .map(|v| Cow::Owned(v.to_owned())) + } +} + impl<'i, T, SV, BH> resolve::InputValueAs<'i, Box, SV, BH> for [T] where Vec: resolve::InputValue<'i, SV, BH>, diff --git a/juniper/src/types/str.rs b/juniper/src/types/str.rs index a5129933..5b874073 100644 --- a/juniper/src/types/str.rs +++ b/juniper/src/types/str.rs @@ -2,7 +2,7 @@ //! //! [`str`]: primitive@std::str -use std::{rc::Rc, sync::Arc}; +use std::{borrow::Cow, rc::Rc, sync::Arc}; use futures::future; @@ -84,6 +84,19 @@ impl resolve::InputValueAsRef for str { } } +impl<'me, 'i, SV> resolve::InputValueAs<'i, Cow<'me, Self>, SV> for str +where + 'i: 'me, + SV: 'i, + Self: resolve::InputValueAsRef, +{ + type Error = >::Error; + + fn try_from_input_value(v: &'i graphql::InputValue) -> Result, Self::Error> { + >::try_from_input_value(v).map(Cow::Borrowed) + } +} + impl<'i, SV> resolve::InputValueAs<'i, Box, SV> for str where SV: 'i, @@ -140,6 +153,17 @@ where fn assert_input_type() {} } +impl<'me, 'i, TI, SV> graphql::InputTypeAs<'i, Cow<'me, Self>, TI, SV> for str +where + Self: graphql::Type + + resolve::ToInputValue + + resolve::InputValueAs<'i, Cow<'me, Self>, SV>, + TI: ?Sized, + SV: 'i, +{ + fn assert_input_type() {} +} + impl<'i, TI, SV> graphql::InputTypeAs<'i, Box, TI, SV> for str where Self: graphql::Type @@ -192,6 +216,17 @@ where fn assert_scalar() {} } +impl<'me, 'i, TI, CX, SV> graphql::ScalarAs<'i, Cow<'me, Self>, TI, CX, SV> for str +where + Self: graphql::InputTypeAs<'i, Cow<'me, Self>, TI, SV> + + graphql::OutputType + + resolve::ScalarToken, + TI: ?Sized, + SV: 'i, +{ + fn assert_scalar() {} +} + impl<'i, TI, CX, SV> graphql::ScalarAs<'i, Box, TI, CX, SV> for str where Self: graphql::InputTypeAs<'i, Box, TI, SV>