use crate::parser::types::Field; use crate::registry::Registry; use crate::{ registry, ContainerType, ContextSelectionSet, FieldResult, InputValueResult, Positioned, Result, Value, }; use std::borrow::Cow; /// Represents a GraphQL type /// /// All GraphQL types implement this trait, such as `Scalar`, `Object`, `Union` ... pub trait Type { /// Type the name. fn type_name() -> Cow<'static, str>; /// Qualified typename. fn qualified_type_name() -> String { format!("{}!", Self::type_name()) } /// Introspection type name /// /// Is the return value of field `__typename`, the interface and union should return the current type, and the others return `Type::type_name`. fn introspection_type_name(&self) -> Cow<'static, str> { Self::type_name() } /// Create type information in the registry and return qualified typename. fn create_type_info(registry: &mut registry::Registry) -> String; } /// Represents a GraphQL input value pub trait InputValueType: Type + Sized { /// Parse from `Value`. None represents undefined. fn parse(value: Option) -> InputValueResult; /// Convert to a `Value` for introspection. fn to_value(&self) -> Value; } /// Represents a GraphQL output value #[async_trait::async_trait] pub trait OutputValueType: Type { /// Resolve an output value to `serde_json::Value`. async fn resolve( &self, ctx: &ContextSelectionSet<'_>, field: &Positioned, ) -> Result; } impl Type for &T { fn type_name() -> Cow<'static, str> { T::type_name() } fn create_type_info(registry: &mut Registry) -> String { T::create_type_info(registry) } } #[async_trait::async_trait] impl OutputValueType for &T { #[allow(clippy::trivially_copy_pass_by_ref)] async fn resolve( &self, ctx: &ContextSelectionSet<'_>, field: &Positioned, ) -> Result { T::resolve(*self, ctx, field).await } } impl Type for FieldResult { fn type_name() -> Cow<'static, str> { T::type_name() } fn qualified_type_name() -> String { T::qualified_type_name() } fn create_type_info(registry: &mut registry::Registry) -> String { T::create_type_info(registry) } } #[async_trait::async_trait] impl OutputValueType for FieldResult { async fn resolve( &self, ctx: &ContextSelectionSet<'_>, field: &Positioned, ) -> crate::Result { match self { Ok(value) => Ok(OutputValueType::resolve(value, ctx, field).await?), Err(err) => Err(err .clone() .into_error_with_path(field.pos, ctx.path_node.as_ref())), } } } /// A GraphQL object. pub trait ObjectType: ContainerType {} #[async_trait::async_trait] impl ObjectType for &T {} /// A GraphQL interface. pub trait InterfaceType: ContainerType {} /// A GraphQL interface. pub trait UnionType: ContainerType {} /// A GraphQL input object. pub trait InputObjectType: InputValueType {}