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.
use std::{marker::PhantomData, sync::atomic::AtomicPtr};
/// Default standard behavior of GraphQL types implementation.
#[derive(Debug)]
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::{
borrow::Cow,
cmp::Ordering,
collections::HashMap,
collections::{hash_map, HashMap},
fmt::{Debug, Display},
sync::{Arc, RwLock},
};
@ -1190,30 +1190,19 @@ impl<'r, S: 'r> Registry<'r, S> {
}
}
/// Returns a [`Type`] meta information for the specified [`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.
/// Returns an entry with a [`Type`] meta information for the specified
/// named [`graphql::Type`], registered in this [`Registry`].
///
/// [`graphql::Type`]: resolve::Type
/// [`TypeName`]: resolve::TypeName
pub fn get_type_new<T, Info>(&mut self, info: &Info) -> Type<'r>
pub fn entry_type<T, TI>(
&mut self,
type_info: &TI,
) -> hash_map::Entry<'_, Name, MetaType<'r, S>>
where
T: resolve::Type<Info, S> + resolve::TypeName<Info> + ?Sized,
Info: ?Sized,
T: resolve::TypeName<TI> + ?Sized,
TI: ?Sized,
{
let name = T::type_name(info);
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()
self.types.entry(T::type_name(type_info).parse().unwrap())
}
/// Creates a [`Field`] with the provided `name`.
@ -1306,19 +1295,20 @@ impl<'r, S: 'r> Registry<'r, S> {
// TODO: Allow using references.
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`]: 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
T: resolve::TypeName<Info> + resolve::ScalarToken<S> + resolve::InputValueAsRef<S> + ?Sized,
Info: ?Sized,
T: resolve::TypeName<TI> + resolve::InputValueAsRef<S> + resolve::ScalarToken<S> + ?Sized,
TI: ?Sized,
{
// 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.
///

View file

@ -54,6 +54,20 @@ pub struct ScalarMeta<'a, 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.
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>>;
/// List type metadata
#[derive(Debug)]
#[derive(Clone, Debug)]
pub struct ListMeta<'a> {
#[doc(hidden)]
pub of_type: Type<'a>,
@ -71,14 +85,14 @@ pub struct ListMeta<'a> {
}
/// Nullable type metadata
#[derive(Debug)]
#[derive(Clone, Debug)]
pub struct NullableMeta<'a> {
#[doc(hidden)]
pub of_type: Type<'a>,
}
/// Object type metadata
#[derive(Debug)]
#[derive(Clone, Debug)]
pub struct ObjectMeta<'a, S> {
#[doc(hidden)]
pub name: Cow<'a, str>,
@ -101,8 +115,21 @@ pub struct EnumMeta<'a, 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
#[derive(Debug)]
#[derive(Clone, Debug)]
pub struct InterfaceMeta<'a, S> {
#[doc(hidden)]
pub name: Cow<'a, str>,
@ -113,7 +140,7 @@ pub struct InterfaceMeta<'a, S> {
}
/// Union type metadata
#[derive(Debug)]
#[derive(Clone, Debug)]
pub struct UnionMeta<'a> {
#[doc(hidden)]
pub name: Cow<'a, str>,
@ -124,6 +151,7 @@ pub struct UnionMeta<'a> {
}
/// Input object metadata
#[derive(Clone)]
pub struct InputObjectMeta<'a, S> {
#[doc(hidden)]
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
/// is inserted into a registry to indicate existence.
#[derive(Debug)]
#[derive(Clone, Debug)]
pub struct PlaceholderMeta<'a> {
#[doc(hidden)]
pub of_type: Type<'a>,
}
/// Generic type metadata
#[derive(Debug)]
#[derive(Clone, Debug)]
pub enum MetaType<'a, S = DefaultScalarValue> {
#[doc(hidden)]
Scalar(ScalarMeta<'a, S>),
@ -168,7 +196,7 @@ pub enum MetaType<'a, S = DefaultScalarValue> {
}
/// Metadata for a field
#[derive(Debug, Clone)]
#[derive(Clone, Debug)]
pub struct Field<'a, S> {
#[doc(hidden)]
pub name: smartstring::alias::String,
@ -191,7 +219,7 @@ impl<'a, S> Field<'a, S> {
}
/// Metadata for an argument to a field
#[derive(Debug, Clone)]
#[derive(Clone, Debug)]
pub struct Argument<'a, S> {
#[doc(hidden)]
pub name: String,
@ -465,7 +493,7 @@ impl<'a, S> ScalarMeta<'a, S> {
try_parse_fn: try_parse_fn_new::<S, T>,
parse_fn: <T as resolve::ScalarToken<S>>::parse_scalar_token,
}
}
}*/
/// Builds a new [`ScalarMeta`] information with the specified `name` for
/// 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(),
description: 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,
}
}*/
}
/// Sets the `description` of this [`ScalarMeta`] type.
///
@ -847,13 +875,13 @@ where
.map(drop)
.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
T: resolve::InputValueAsRef<S> + ?Sized,
T: resolve::InputValueAsRef<SV> + ?Sized,
{
T::try_from_input_value(v)
.map(drop)
.map_err(T::Error::into_field_error)
}
*/

View file

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