Re-implement str, vol.1 [skip ci]

This commit is contained in:
tyranron 2022-06-09 18:10:33 +02:00
parent be010e8123
commit 88046e3ce4
No known key found for this signature in database
GPG key ID: 762E144FB230A4F0
4 changed files with 143 additions and 90 deletions

View file

@ -1,5 +1,21 @@
//! Default GraphQL behaviors. //! Default GraphQL behaviors.
use std::{marker::PhantomData, sync::atomic::AtomicPtr};
/// Default standard behavior of GraphQL types implementation. /// Default standard behavior of GraphQL types implementation.
#[derive(Debug)] #[derive(Debug)]
pub enum Standard {} pub enum Standard {}
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)
}
}
#[must_use]
pub const fn coerce<T, From: ?Sized>(val: T) -> Coerce<T, From> {
Coerce::wrap(val)
}

View file

@ -3,7 +3,7 @@
use std::{ use std::{
borrow::Cow, borrow::Cow,
cmp::Ordering, cmp::Ordering,
collections::HashMap, collections::{hash_map, HashMap},
fmt::{Debug, Display}, fmt::{Debug, Display},
sync::{Arc, RwLock}, sync::{Arc, RwLock},
}; };
@ -1190,30 +1190,19 @@ impl<'r, S: 'r> Registry<'r, S> {
} }
} }
/// Returns a [`Type`] meta information for the specified [`graphql::Type`], /// Returns an entry with a [`Type`] meta information for the specified
/// registered in this [`Registry`]. /// named [`graphql::Type`], registered in this [`Registry`].
///
/// If this [`Registry`] doesn't contain a [`Type`] meta information with
/// such [`TypeName`] before, it will construct the one and store it.
/// ///
/// [`graphql::Type`]: resolve::Type /// [`graphql::Type`]: resolve::Type
/// [`TypeName`]: resolve::TypeName pub fn entry_type<T, TI>(
pub fn get_type_new<T, Info>(&mut self, info: &Info) -> Type<'r> &mut self,
type_info: &TI,
) -> hash_map::Entry<'_, Name, MetaType<'r, S>>
where where
T: resolve::Type<Info, S> + resolve::TypeName<Info> + ?Sized, T: resolve::TypeName<TI> + ?Sized,
Info: ?Sized, TI: ?Sized,
{ {
let name = T::type_name(info); self.types.entry(T::type_name(type_info).parse().unwrap())
let validated_name = name.parse::<Name>().unwrap();
if !self.types.contains_key(name) {
self.insert_placeholder(
validated_name.clone(),
Type::NonNullNamed(Cow::Owned(name.to_string())),
);
let meta = T::meta(self, info);
self.types.insert(validated_name, meta);
}
self.types[name].as_type()
} }
/// Creates a [`Field`] with the provided `name`. /// Creates a [`Field`] with the provided `name`.
@ -1306,19 +1295,20 @@ impl<'r, S: 'r> Registry<'r, S> {
// TODO: Allow using references. // TODO: Allow using references.
ScalarMeta::new_new::<T, _>(T::type_name(info).to_owned()) ScalarMeta::new_new::<T, _>(T::type_name(info).to_owned())
} }
*/
/// Builds a [`ScalarMeta`] information for the [`?Sized`] specified /// Builds a [`ScalarMeta`] information for the specified [`?Sized`]
/// [`graphql::Type`]. /// [`graphql::Type`].
/// ///
/// [`graphql::Type`]: resolve::Type /// [`graphql::Type`]: resolve::Type
pub fn build_scalar_type_unsized<T, Info>(&mut self, info: &Info) -> ScalarMeta<'r, S> pub fn build_scalar_type_unsized<T, TI>(&mut self, type_info: &TI) -> ScalarMeta<'r, S>
where where
T: resolve::TypeName<Info> + resolve::ScalarToken<S> + resolve::InputValueAsRef<S> + ?Sized, T: resolve::TypeName<TI> + resolve::InputValueAsRef<S> + resolve::ScalarToken<S> + ?Sized,
Info: ?Sized, TI: ?Sized,
{ {
// TODO: Allow using references. // TODO: Allow using references.
ScalarMeta::new_unsized::<T, _>(T::type_name(info).to_owned()) ScalarMeta::new_unsized::<T, _>(T::type_name(type_info).to_owned())
}*/ }
/// Creates a [`ListMeta`] type. /// Creates a [`ListMeta`] type.
/// ///

View file

@ -54,6 +54,20 @@ pub struct ScalarMeta<'a, S> {
pub(crate) parse_fn: ScalarTokenParseFn<S>, pub(crate) parse_fn: ScalarTokenParseFn<S>,
} }
// Manual implementation is required here to omit redundant `S: Clone` trait
// bound, imposed by `#[derive(Clone)]`.
impl<'a, S> Clone for ScalarMeta<'a, S> {
fn clone(&self) -> Self {
Self {
name: self.name.clone(),
description: self.description.clone(),
specified_by_url: self.specified_by_url.clone(),
try_parse_fn: self.try_parse_fn,
parse_fn: self.parse_fn,
}
}
}
/// Shortcut for an [`InputValue`] parsing function. /// Shortcut for an [`InputValue`] parsing function.
pub type InputValueParseFn<S> = for<'b> fn(&'b InputValue<S>) -> Result<(), FieldError<S>>; pub type InputValueParseFn<S> = for<'b> fn(&'b InputValue<S>) -> Result<(), FieldError<S>>;
@ -61,7 +75,7 @@ pub type InputValueParseFn<S> = for<'b> fn(&'b InputValue<S>) -> Result<(), Fiel
pub type ScalarTokenParseFn<S> = for<'b> fn(ScalarToken<'b>) -> Result<S, ParseError<'b>>; pub type ScalarTokenParseFn<S> = for<'b> fn(ScalarToken<'b>) -> Result<S, ParseError<'b>>;
/// List type metadata /// List type metadata
#[derive(Debug)] #[derive(Clone, Debug)]
pub struct ListMeta<'a> { pub struct ListMeta<'a> {
#[doc(hidden)] #[doc(hidden)]
pub of_type: Type<'a>, pub of_type: Type<'a>,
@ -71,14 +85,14 @@ pub struct ListMeta<'a> {
} }
/// Nullable type metadata /// Nullable type metadata
#[derive(Debug)] #[derive(Clone, Debug)]
pub struct NullableMeta<'a> { pub struct NullableMeta<'a> {
#[doc(hidden)] #[doc(hidden)]
pub of_type: Type<'a>, pub of_type: Type<'a>,
} }
/// Object type metadata /// Object type metadata
#[derive(Debug)] #[derive(Clone, Debug)]
pub struct ObjectMeta<'a, S> { pub struct ObjectMeta<'a, S> {
#[doc(hidden)] #[doc(hidden)]
pub name: Cow<'a, str>, pub name: Cow<'a, str>,
@ -101,8 +115,21 @@ pub struct EnumMeta<'a, S> {
pub(crate) try_parse_fn: InputValueParseFn<S>, pub(crate) try_parse_fn: InputValueParseFn<S>,
} }
// Manual implementation is required here to omit redundant `S: Clone` trait
// bound, imposed by `#[derive(Clone)]`.
impl<'a, S> Clone for EnumMeta<'a, S> {
fn clone(&self) -> Self {
Self {
name: self.name.clone(),
description: self.description.clone(),
values: self.values.clone(),
try_parse_fn: self.try_parse_fn,
}
}
}
/// Interface type metadata /// Interface type metadata
#[derive(Debug)] #[derive(Clone, Debug)]
pub struct InterfaceMeta<'a, S> { pub struct InterfaceMeta<'a, S> {
#[doc(hidden)] #[doc(hidden)]
pub name: Cow<'a, str>, pub name: Cow<'a, str>,
@ -113,7 +140,7 @@ pub struct InterfaceMeta<'a, S> {
} }
/// Union type metadata /// Union type metadata
#[derive(Debug)] #[derive(Clone, Debug)]
pub struct UnionMeta<'a> { pub struct UnionMeta<'a> {
#[doc(hidden)] #[doc(hidden)]
pub name: Cow<'a, str>, pub name: Cow<'a, str>,
@ -124,6 +151,7 @@ pub struct UnionMeta<'a> {
} }
/// Input object metadata /// Input object metadata
#[derive(Clone)]
pub struct InputObjectMeta<'a, S> { pub struct InputObjectMeta<'a, S> {
#[doc(hidden)] #[doc(hidden)]
pub name: Cow<'a, str>, pub name: Cow<'a, str>,
@ -138,14 +166,14 @@ pub struct InputObjectMeta<'a, S> {
/// ///
/// After a type's `meta` method has been called but before it has returned, a placeholder type /// After a type's `meta` method has been called but before it has returned, a placeholder type
/// is inserted into a registry to indicate existence. /// is inserted into a registry to indicate existence.
#[derive(Debug)] #[derive(Clone, Debug)]
pub struct PlaceholderMeta<'a> { pub struct PlaceholderMeta<'a> {
#[doc(hidden)] #[doc(hidden)]
pub of_type: Type<'a>, pub of_type: Type<'a>,
} }
/// Generic type metadata /// Generic type metadata
#[derive(Debug)] #[derive(Clone, Debug)]
pub enum MetaType<'a, S = DefaultScalarValue> { pub enum MetaType<'a, S = DefaultScalarValue> {
#[doc(hidden)] #[doc(hidden)]
Scalar(ScalarMeta<'a, S>), Scalar(ScalarMeta<'a, S>),
@ -168,7 +196,7 @@ pub enum MetaType<'a, S = DefaultScalarValue> {
} }
/// Metadata for a field /// Metadata for a field
#[derive(Debug, Clone)] #[derive(Clone, Debug)]
pub struct Field<'a, S> { pub struct Field<'a, S> {
#[doc(hidden)] #[doc(hidden)]
pub name: smartstring::alias::String, pub name: smartstring::alias::String,
@ -191,7 +219,7 @@ impl<'a, S> Field<'a, S> {
} }
/// Metadata for an argument to a field /// Metadata for an argument to a field
#[derive(Debug, Clone)] #[derive(Clone, Debug)]
pub struct Argument<'a, S> { pub struct Argument<'a, S> {
#[doc(hidden)] #[doc(hidden)]
pub name: String, pub name: String,
@ -465,7 +493,7 @@ impl<'a, S> ScalarMeta<'a, S> {
try_parse_fn: try_parse_fn_new::<S, T>, try_parse_fn: try_parse_fn_new::<S, T>,
parse_fn: <T as resolve::ScalarToken<S>>::parse_scalar_token, parse_fn: <T as resolve::ScalarToken<S>>::parse_scalar_token,
} }
} }*/
/// Builds a new [`ScalarMeta`] information with the specified `name` for /// Builds a new [`ScalarMeta`] information with the specified `name` for
/// the [`?Sized`] `T`ype that may only be parsed as a reference. /// the [`?Sized`] `T`ype that may only be parsed as a reference.
@ -481,10 +509,10 @@ impl<'a, S> ScalarMeta<'a, S> {
name: name.into(), name: name.into(),
description: None, description: None,
specified_by_url: None, specified_by_url: None,
try_parse_fn: try_parse_unsized_fn::<S, T>, try_parse_fn: try_parse_unsized_fn::<T, S>,
parse_fn: <T as resolve::ScalarToken<S>>::parse_scalar_token, parse_fn: <T as resolve::ScalarToken<S>>::parse_scalar_token,
} }
}*/ }
/// Sets the `description` of this [`ScalarMeta`] type. /// Sets the `description` of this [`ScalarMeta`] type.
/// ///
@ -847,13 +875,13 @@ where
.map(drop) .map(drop)
.map_err(T::Error::into_field_error) .map_err(T::Error::into_field_error)
} }
*/
fn try_parse_unsized_fn<S, T>(v: &InputValue<S>) -> Result<(), FieldError<S>> fn try_parse_unsized_fn<T, SV>(v: &InputValue<SV>) -> Result<(), FieldError<SV>>
where where
T: resolve::InputValueAsRef<S> + ?Sized, T: resolve::InputValueAsRef<SV> + ?Sized,
{ {
T::try_from_input_value(v) T::try_from_input_value(v)
.map(drop) .map(drop)
.map_err(T::Error::into_field_error) .map_err(T::Error::into_field_error)
} }
*/

View file

@ -13,24 +13,28 @@ use crate::{
reflect, resolve, BoxFuture, ExecutionResult, Executor, Registry, ScalarValue, Selection, reflect, resolve, BoxFuture, ExecutionResult, Executor, Registry, ScalarValue, Selection,
}; };
/* impl<TI: ?Sized, SV: ScalarValue> resolve::Type<TI, SV> for str {
impl<Info: ?Sized, S: ScalarValue> resolve::Type<Info, S> for str { fn meta<'r>(registry: &mut Registry<'r, SV>, type_info: &TI) -> MetaType<'r, SV>
fn meta<'r>(registry: &mut Registry<'r, S>, info: &Info) -> MetaType<'r, S>
where where
S: 'r, SV: 'r,
{ {
let meta = registry
.build_scalar_type_unsized::<Self, _>(type_info)
.into_meta();
registry registry
.build_scalar_type_unsized::<Self, _>(info) .entry_type::<Self, _>(type_info)
.into_meta() .or_insert(meta)
.clone()
} }
} }
impl<Info: ?Sized> resolve::TypeName<Info> for str { impl<TI: ?Sized> resolve::TypeName<TI> for str {
fn type_name(_: &Info) -> &'static str { fn type_name(_: &TI) -> &'static str {
<Self as reflect::BaseType<()>>::NAME <Self as reflect::BaseType>::NAME
} }
} }
/*
impl<Info, Ctx, S> resolve::Value<Info, Ctx, S> for str impl<Info, Ctx, S> resolve::Value<Info, Ctx, S> for str
where where
Info: ?Sized, Info: ?Sized,
@ -76,49 +80,65 @@ where
} }
} }
impl<S: ScalarValue> resolve::InputValueAsRef<S> for str { */
impl<SV: ScalarValue> resolve::InputValueAsRef<SV> for str {
type Error = String; type Error = String;
fn try_from_input_value(v: &graphql::InputValue<S>) -> Result<&Self, Self::Error> { fn try_from_input_value(v: &graphql::InputValue<SV>) -> Result<&Self, Self::Error> {
v.as_string_value() v.as_string_value()
.ok_or_else(|| format!("Expected `String`, found: {}", v)) .ok_or_else(|| format!("Expected `String`, found: {}", v))
} }
} }
impl<'inp, S: ScalarValue> resolve::InputValueAsBox<'inp, S> for str { impl<'i, SV> resolve::InputValueAs<'i, Box<str>, SV> for str
type Error = String;
fn try_from_input_value(v: &'inp graphql::InputValue<S>) -> Result<Box<Self>, Self::Error> {
<str as resolve::InputValueAsRef<S>>::try_from_input_value(v).map(Into::into)
}
}
impl<'inp, S: ScalarValue> resolve::InputValueAsArc<'inp, S> for str {
type Error = String;
fn try_from_input_value(v: &'inp graphql::InputValue<S>) -> Result<Arc<Self>, Self::Error> {
<str as resolve::InputValueAsRef<S>>::try_from_input_value(v).map(Into::into)
}
}
impl<'inp, S: ScalarValue> resolve::InputValueAsRc<'inp, S> for str {
type Error = String;
fn try_from_input_value(v: &'inp graphql::InputValue<S>) -> Result<Rc<Self>, Self::Error> {
<str as resolve::InputValueAsRef<S>>::try_from_input_value(v).map(Into::into)
}
}
impl<S> resolve::ScalarToken<S> for str
where where
String: resolve::ScalarToken<S>, SV: 'i,
Self: resolve::InputValueAsRef<SV>,
{ {
fn parse_scalar_token(token: ScalarToken<'_>) -> Result<S, ParseError<'_>> { type Error = <Self as resolve::InputValueAsRef<SV>>::Error;
<String as resolve::ScalarToken<S>>::parse_scalar_token(token)
fn try_from_input_value(v: &'i graphql::InputValue<SV>) -> Result<Box<Self>, Self::Error> {
<Self as resolve::InputValueAsRef<SV>>::try_from_input_value(v).map(Into::into)
} }
} }
impl<'i, SV> resolve::InputValueAs<'i, Rc<str>, SV> for str
where
SV: 'i,
Self: resolve::InputValueAsRef<SV>,
{
type Error = <Self as resolve::InputValueAsRef<SV>>::Error;
fn try_from_input_value(v: &'i graphql::InputValue<SV>) -> Result<Rc<Self>, Self::Error> {
<Self as resolve::InputValueAsRef<SV>>::try_from_input_value(v).map(Into::into)
}
}
impl<'i, SV> resolve::InputValueAs<'i, Arc<str>, SV> for str
where
SV: 'i,
Self: resolve::InputValueAsRef<SV>,
{
type Error = <Self as resolve::InputValueAsRef<SV>>::Error;
fn try_from_input_value(v: &'i graphql::InputValue<SV>) -> Result<Arc<Self>, Self::Error> {
<Self as resolve::InputValueAsRef<SV>>::try_from_input_value(v).map(Into::into)
}
}
impl<SV> resolve::ScalarToken<SV> for str
//TODO: where String: resolve::ScalarToken<SV>,
where
String: crate::ParseScalarValue<SV>,
{
fn parse_scalar_token(token: ScalarToken<'_>) -> Result<SV, ParseError<'_>> {
// TODO: <String as resolve::ScalarToken<SV>>::parse_scalar_token(token)
<String as crate::ParseScalarValue<SV>>::from_str(token)
}
}
/* /*
impl<'i, Info, S: 'i> graphql::InputType<'i, Info, S> for str impl<'i, Info, S: 'i> graphql::InputType<'i, Info, S> for str
where where
Self: resolve::Type<Info, S> + resolve::ToInputValue<S> + resolve::InputValue<'i, S>, Self: resolve::Type<Info, S> + resolve::ToInputValue<S> + resolve::InputValue<'i, S>,
@ -126,7 +146,7 @@ where
{ {
fn assert_input_type() {} fn assert_input_type() {}
} }
*/
impl<S> graphql::OutputType<S> for str { impl<S> graphql::OutputType<S> for str {
fn assert_output_type() {} fn assert_output_type() {}
@ -134,17 +154,16 @@ impl<S> graphql::OutputType<S> for str {
impl<S> graphql::Scalar<S> for str { impl<S> graphql::Scalar<S> for str {
fn assert_scalar() {} fn assert_scalar() {}
}*/
impl reflect::BaseType for str {
const NAME: reflect::Type = "String"; // TODO: <String as reflect::BaseType<BH>>::NAME;
} }
impl<S> reflect::BaseType<S> for str { impl reflect::BaseSubTypes for str {
const NAME: reflect::Type = <String as reflect::BaseType<S>>::NAME; const NAMES: reflect::Types = &[<Self as reflect::BaseType>::NAME];
} }
impl<S> reflect::BaseSubTypes<S> for str { impl reflect::WrappedType for str {
const NAMES: reflect::Types = &[<Self as reflect::BaseType<S>>::NAME];
}
impl<S> reflect::WrappedType<S> for str {
const VALUE: reflect::WrappedValue = reflect::wrap::SINGULAR; const VALUE: reflect::WrappedValue = reflect::wrap::SINGULAR;
} }
*/