Restructure types module
This commit is contained in:
parent
1af9ce5b95
commit
f204841d1f
|
@ -61,7 +61,7 @@ pub fn generate(enum_args: &args::Enum, input: &DeriveInput) -> Result<TokenStre
|
|||
.unwrap_or_else(|| quote! {None});
|
||||
enum_items.push(quote! { #(#item_attrs)* #item_ident});
|
||||
items.push(quote! {
|
||||
#crate_name::EnumItem {
|
||||
#crate_name::resolver_utils::EnumItem {
|
||||
name: #gql_item_name,
|
||||
value: #ident::#item_ident,
|
||||
}
|
||||
|
@ -77,8 +77,8 @@ pub fn generate(enum_args: &args::Enum, input: &DeriveInput) -> Result<TokenStre
|
|||
|
||||
let expanded = quote! {
|
||||
#[allow(clippy::all, clippy::pedantic)]
|
||||
impl #crate_name::EnumType for #ident {
|
||||
fn items() -> &'static [#crate_name::EnumItem<#ident>] {
|
||||
impl #crate_name::resolver_utils::EnumType for #ident {
|
||||
fn items() -> &'static [#crate_name::resolver_utils::EnumItem<#ident>] {
|
||||
&[#(#items),*]
|
||||
}
|
||||
}
|
||||
|
@ -107,18 +107,18 @@ pub fn generate(enum_args: &args::Enum, input: &DeriveInput) -> Result<TokenStre
|
|||
#[allow(clippy::all, clippy::pedantic)]
|
||||
impl #crate_name::InputValueType for #ident {
|
||||
fn parse(value: Option<#crate_name::Value>) -> #crate_name::InputValueResult<Self> {
|
||||
#crate_name::EnumType::parse_enum(value.unwrap_or_default())
|
||||
#crate_name::resolver_utils::parse_enum(value.unwrap_or_default())
|
||||
}
|
||||
|
||||
fn to_value(&self) -> #crate_name::Value {
|
||||
#crate_name::EnumType::to_value(self)
|
||||
#crate_name::resolver_utils::enum_value(*self)
|
||||
}
|
||||
}
|
||||
|
||||
#[#crate_name::async_trait::async_trait]
|
||||
impl #crate_name::OutputValueType for #ident {
|
||||
async fn resolve(&self, _: &#crate_name::ContextSelectionSet<'_>, _field: &#crate_name::Positioned<#crate_name::parser::types::Field>) -> #crate_name::Result<#crate_name::serde_json::Value> {
|
||||
Ok(#crate_name::EnumType::to_value(self).into_json().unwrap())
|
||||
Ok(#crate_name::resolver_utils::enum_value(*self).into_json().unwrap())
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
11
src/lib.rs
11
src/lib.rs
|
@ -105,16 +105,15 @@ mod look_ahead;
|
|||
mod model;
|
||||
mod request;
|
||||
mod response;
|
||||
mod scalars;
|
||||
mod schema;
|
||||
mod serialize_resp;
|
||||
mod subscription;
|
||||
mod types;
|
||||
mod validation;
|
||||
|
||||
pub mod extensions;
|
||||
pub mod guard;
|
||||
pub mod validators;
|
||||
pub mod types;
|
||||
|
||||
#[doc(hidden)]
|
||||
pub mod resolver_utils;
|
||||
|
@ -145,15 +144,11 @@ pub use parser::{types::ConstValue as Value, Pos, Positioned};
|
|||
pub use registry::CacheControl;
|
||||
pub use request::Request;
|
||||
pub use response::Response;
|
||||
pub use scalars::{Any, Json, OutputJson, ID};
|
||||
pub use schema::{Schema, SchemaBuilder, SchemaEnv};
|
||||
pub use serde_json::Number;
|
||||
pub use subscription::SimpleBroker;
|
||||
pub use types::{
|
||||
connection, EmptyMutation, EmptySubscription, MaybeUndefined, MergedObject,
|
||||
MergedObjectSubscriptionTail, MergedObjectTail, Upload,
|
||||
};
|
||||
pub use validation::ValidationMode;
|
||||
pub use types::*;
|
||||
|
||||
/// Result type
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
@ -168,8 +163,6 @@ pub mod registry;
|
|||
pub use base::{InputObjectType, InputValueType, OutputValueType};
|
||||
#[doc(hidden)]
|
||||
pub use subscription::SubscriptionType;
|
||||
#[doc(hidden)]
|
||||
pub use types::{EnumItem, EnumType};
|
||||
|
||||
/// Define a GraphQL object with methods
|
||||
///
|
||||
|
|
45
src/resolver_utils/enum.rs
Normal file
45
src/resolver_utils/enum.rs
Normal file
|
@ -0,0 +1,45 @@
|
|||
use crate::parser::types::Name;
|
||||
use crate::{InputValueError, InputValueResult, Type, Value};
|
||||
|
||||
/// A variant of an enum.
|
||||
pub struct EnumItem<T> {
|
||||
/// The name of the variant.
|
||||
pub name: &'static str,
|
||||
/// The value of the variant.
|
||||
pub value: T,
|
||||
}
|
||||
|
||||
/// An enum value.
|
||||
pub trait EnumType: Type + Sized + Eq + Send + Copy + Sized + 'static {
|
||||
/// Get a list of the variants of the enum value.
|
||||
fn items() -> &'static [EnumItem<Self>];
|
||||
}
|
||||
|
||||
/// Parse a value as an enum value.
|
||||
///
|
||||
/// This can be used to implement `InputValueType::parse`.
|
||||
pub fn parse_enum<T: EnumType>(value: Value) -> InputValueResult<T> {
|
||||
let value = match &value {
|
||||
Value::Enum(s) => s,
|
||||
Value::String(s) => s.as_str(),
|
||||
_ => return Err(InputValueError::ExpectedType(value)),
|
||||
};
|
||||
|
||||
T::items()
|
||||
.iter()
|
||||
.find(|item| item.name == value)
|
||||
.map(|item| item.value)
|
||||
.ok_or_else(|| InputValueError::Custom(format!(
|
||||
r#"Enumeration type "{}" does not contain the value "{}""#,
|
||||
T::type_name(),
|
||||
value,
|
||||
)))
|
||||
}
|
||||
|
||||
/// Convert the enum value into a GraphQL value.
|
||||
///
|
||||
/// This can be used to implement `InputValueType::to_value` or `OutputValueType::resolve`.
|
||||
pub fn enum_value<T: EnumType>(value: T) -> Value {
|
||||
let item = T::items().iter().find(|item| item.value == value).unwrap();
|
||||
Value::Enum(Name::new_unchecked(item.name.to_owned()))
|
||||
}
|
|
@ -1,5 +1,7 @@
|
|||
//! Utilities for implementing `OutputValueType::resolve`.
|
||||
|
||||
mod object;
|
||||
mod r#enum;
|
||||
|
||||
pub use object::*;
|
||||
pub use r#enum::*;
|
||||
|
|
|
@ -1,84 +0,0 @@
|
|||
mod any;
|
||||
mod bool;
|
||||
mod datetime;
|
||||
mod floats;
|
||||
mod id;
|
||||
mod integers;
|
||||
mod json;
|
||||
mod naive_time;
|
||||
mod string;
|
||||
mod uuid;
|
||||
|
||||
#[cfg(feature = "bson")]
|
||||
mod bson;
|
||||
#[cfg(feature = "chrono_tz")]
|
||||
mod chrono_tz;
|
||||
#[cfg(feature = "url")]
|
||||
mod url;
|
||||
|
||||
pub use any::Any;
|
||||
pub use id::ID;
|
||||
pub use json::{Json, OutputJson};
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::ID;
|
||||
use crate::Type;
|
||||
use bson::oid::ObjectId;
|
||||
use chrono::{DateTime, FixedOffset, Local, NaiveDate, NaiveTime, Utc};
|
||||
use uuid::Uuid;
|
||||
|
||||
#[test]
|
||||
fn test_scalar_type() {
|
||||
assert_eq!(<bool as Type>::type_name(), "Boolean");
|
||||
assert_eq!(<bool as Type>::qualified_type_name(), "Boolean!");
|
||||
|
||||
assert_eq!(<i32 as Type>::type_name(), "Int");
|
||||
assert_eq!(<i32 as Type>::qualified_type_name(), "Int!");
|
||||
|
||||
assert_eq!(<f32 as Type>::type_name(), "Float");
|
||||
assert_eq!(<f32 as Type>::qualified_type_name(), "Float!");
|
||||
|
||||
assert_eq!(<&str as Type>::type_name(), "String");
|
||||
assert_eq!(<&str as Type>::qualified_type_name(), "String!");
|
||||
|
||||
assert_eq!(<String as Type>::type_name(), "String");
|
||||
assert_eq!(<String as Type>::qualified_type_name(), "String!");
|
||||
|
||||
assert_eq!(<ID as Type>::type_name(), "ID");
|
||||
assert_eq!(<ID as Type>::qualified_type_name(), "ID!");
|
||||
|
||||
assert_eq!(<NaiveDate as Type>::type_name(), "NaiveDate");
|
||||
assert_eq!(<NaiveDate as Type>::qualified_type_name(), "NaiveDate!");
|
||||
|
||||
assert_eq!(<NaiveTime as Type>::type_name(), "NaiveTime");
|
||||
assert_eq!(<NaiveTime as Type>::qualified_type_name(), "NaiveTime!");
|
||||
|
||||
assert_eq!(<DateTime::<Utc> as Type>::type_name(), "DateTime");
|
||||
assert_eq!(
|
||||
<DateTime::<Utc> as Type>::qualified_type_name(),
|
||||
"DateTime!"
|
||||
);
|
||||
|
||||
assert_eq!(<DateTime::<Local> as Type>::type_name(), "DateTime");
|
||||
assert_eq!(
|
||||
<DateTime::<Local> as Type>::qualified_type_name(),
|
||||
"DateTime!"
|
||||
);
|
||||
|
||||
assert_eq!(<DateTime::<FixedOffset> as Type>::type_name(), "DateTime");
|
||||
assert_eq!(
|
||||
<DateTime::<FixedOffset> as Type>::qualified_type_name(),
|
||||
"DateTime!"
|
||||
);
|
||||
|
||||
assert_eq!(<Uuid as Type>::type_name(), "UUID");
|
||||
assert_eq!(<Uuid as Type>::qualified_type_name(), "UUID!");
|
||||
|
||||
#[cfg(feature = "bson")]
|
||||
{
|
||||
assert_eq!(<ObjectId as Type>::type_name(), "ObjectId");
|
||||
assert_eq!(<ObjectId as Type>::qualified_type_name(), "ObjectId!");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
use crate::parser::types::Name;
|
||||
use crate::{InputValueError, InputValueResult, Type, Value};
|
||||
|
||||
#[allow(missing_docs)]
|
||||
pub struct EnumItem<T> {
|
||||
pub name: &'static str,
|
||||
pub value: T,
|
||||
}
|
||||
|
||||
#[allow(missing_docs)]
|
||||
#[async_trait::async_trait]
|
||||
pub trait EnumType: Type + Sized + Eq + Send + Copy + Sized + 'static {
|
||||
fn items() -> &'static [EnumItem<Self>];
|
||||
|
||||
fn parse_enum(value: Value) -> InputValueResult<Self> {
|
||||
let value = match &value {
|
||||
Value::Enum(s) => s,
|
||||
Value::String(s) => s.as_str(),
|
||||
_ => return Err(InputValueError::ExpectedType(value)),
|
||||
};
|
||||
|
||||
let items = Self::items();
|
||||
for item in items {
|
||||
if item.name == value {
|
||||
return Ok(item.value);
|
||||
}
|
||||
}
|
||||
Err(InputValueError::Custom(format!(
|
||||
r#"Enumeration type "{}" does not contain the value "{}""#,
|
||||
Self::type_name(),
|
||||
value
|
||||
)))
|
||||
}
|
||||
|
||||
fn to_value(&self) -> Value {
|
||||
let items = Self::items();
|
||||
for item in items {
|
||||
if item.value == *self {
|
||||
return Value::Enum(Name::new_unchecked(item.name.to_owned()));
|
||||
}
|
||||
}
|
||||
unreachable!()
|
||||
}
|
||||
}
|
16
src/types/external/mod.rs
vendored
Normal file
16
src/types/external/mod.rs
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
//! Implementations of `Type`, `ScalarType`, etc on external types.
|
||||
|
||||
mod string;
|
||||
mod list;
|
||||
mod optional;
|
||||
mod bool;
|
||||
mod integers;
|
||||
mod floats;
|
||||
mod url;
|
||||
mod uuid;
|
||||
mod datetime;
|
||||
|
||||
#[cfg(feature = "bson")]
|
||||
mod bson;
|
||||
#[cfg(feature = "chrono_tz")]
|
||||
mod chrono_tz;
|
|
@ -10,7 +10,7 @@ use std::ops::{Deref, DerefMut};
|
|||
///
|
||||
/// The input is a `&str`, `String`, `usize` or `uuid::UUID`, and the output is a string.
|
||||
#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Serialize, Deserialize)]
|
||||
pub struct ID(String);
|
||||
pub struct ID(pub String);
|
||||
|
||||
impl Deref for ID {
|
||||
type Target = String;
|
||||
|
@ -26,18 +26,15 @@ impl DerefMut for ID {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T> From<T> for ID
|
||||
where
|
||||
T: std::fmt::Display,
|
||||
{
|
||||
impl<T: std::fmt::Display> From<T> for ID {
|
||||
fn from(value: T) -> Self {
|
||||
ID(value.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<String> for ID {
|
||||
fn into(self) -> String {
|
||||
self.0
|
||||
impl From<ID> for String {
|
||||
fn from(id: ID) -> Self {
|
||||
id.0
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -55,7 +52,7 @@ macro_rules! try_from_integers {
|
|||
};
|
||||
}
|
||||
|
||||
try_from_integers!(i8, i16, i32, i64, u8, u16, u32, u64, isize, usize);
|
||||
try_from_integers!(i8, i16, i32, i64, i128, u8, u16, u32, u64, u128, isize, usize);
|
||||
|
||||
impl TryFrom<ID> for uuid::Uuid {
|
||||
type Error = uuid::Error;
|
|
@ -1,19 +1,26 @@
|
|||
//! Useful GraphQL types.
|
||||
|
||||
pub mod connection;
|
||||
|
||||
mod any;
|
||||
mod json;
|
||||
mod empty_mutation;
|
||||
mod empty_subscription;
|
||||
mod r#enum;
|
||||
mod list;
|
||||
mod maybe_undefined;
|
||||
mod merged_object;
|
||||
mod optional;
|
||||
mod query_root;
|
||||
mod upload;
|
||||
mod id;
|
||||
|
||||
mod external;
|
||||
|
||||
pub use any::Any;
|
||||
pub use json::{Json, OutputJson};
|
||||
pub use empty_mutation::EmptyMutation;
|
||||
pub use empty_subscription::EmptySubscription;
|
||||
pub use maybe_undefined::MaybeUndefined;
|
||||
pub use merged_object::{MergedObject, MergedObjectSubscriptionTail, MergedObjectTail};
|
||||
pub use query_root::QueryRoot;
|
||||
pub use r#enum::{EnumItem, EnumType};
|
||||
pub use upload::Upload;
|
||||
pub use id::ID;
|
||||
|
||||
pub(crate) use query_root::QueryRoot;
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
use crate::model::{__Schema, __Type};
|
||||
use crate::parser::types::Field;
|
||||
use crate::resolver_utils::{resolve_object, ObjectType};
|
||||
use crate::scalars::Any;
|
||||
use crate::{
|
||||
registry, Context, ContextSelectionSet, Error, GQLSimpleObject, OutputValueType, Positioned,
|
||||
registry, Any, Context, ContextSelectionSet, Error, GQLSimpleObject, OutputValueType, Positioned,
|
||||
QueryError, Result, Type,
|
||||
};
|
||||
|
||||
|
@ -17,9 +16,9 @@ struct Service {
|
|||
sdl: Option<String>,
|
||||
}
|
||||
|
||||
pub struct QueryRoot<T> {
|
||||
pub inner: T,
|
||||
pub disable_introspection: bool,
|
||||
pub(crate) struct QueryRoot<T> {
|
||||
pub(crate) inner: T,
|
||||
pub(crate) disable_introspection: bool,
|
||||
}
|
||||
|
||||
impl<T: Type> Type for QueryRoot<T> {
|
||||
|
|
Loading…
Reference in New Issue
Block a user