dynamic-graphql 0.10.1

Dynamic GraphQL schema
Documentation
use std::borrow::Cow;

use async_graphql::MaybeUndefined;
use async_graphql::dynamic;

use crate::registry::Registry;
use crate::type_ref_builder::TypeRefBuilder;
use crate::types::GetInputTypeRef;
use crate::types::GetOutputTypeRef;
use crate::types::InputTypeName;
use crate::types::OutputTypeName;
use crate::types::Register;
use crate::types::TypeName;

impl<T> Register for &T
where
    T: Register + 'static,
{
    fn register(registry: Registry) -> Registry {
        registry.register::<T>()
    }
}

impl<T> TypeName for &'_ T
where
    T: TypeName + 'static,
{
    fn get_type_name() -> Cow<'static, str> {
        <T as TypeName>::get_type_name()
    }
}

impl<T: OutputTypeName + 'static> OutputTypeName for &T {}

impl<T: Register + Clone + 'static> Register for Cow<'_, T> {
    fn register(registry: Registry) -> Registry {
        registry.register::<T>()
    }
}
impl<T: OutputTypeName + Clone + 'static> TypeName for Cow<'_, T> {
    fn get_type_name() -> Cow<'static, str> {
        <T as TypeName>::get_type_name()
    }
}

impl<T: OutputTypeName + Clone + 'static> OutputTypeName for Cow<'_, T> {}

impl Register for String {}
impl TypeName for String {
    fn get_type_name() -> Cow<'static, str> {
        dynamic::TypeRef::STRING.into()
    }
}

impl InputTypeName for String {}

impl OutputTypeName for String {}

impl Register for &str {}
impl TypeName for &str {
    fn get_type_name() -> Cow<'static, str> {
        dynamic::TypeRef::STRING.into()
    }
}

impl InputTypeName for &str {}

impl OutputTypeName for &str {}

impl TypeName for str {
    fn get_type_name() -> Cow<'static, str> {
        dynamic::TypeRef::STRING.into()
    }
}

impl Register for str {}
impl InputTypeName for str {}

impl OutputTypeName for str {}

impl Register for async_graphql::ID {}
impl TypeName for async_graphql::ID {
    fn get_type_name() -> Cow<'static, str> {
        dynamic::TypeRef::ID.into()
    }
}

impl InputTypeName for async_graphql::ID {}

impl OutputTypeName for async_graphql::ID {}

impl Register for bool {}
impl TypeName for bool {
    fn get_type_name() -> Cow<'static, str> {
        dynamic::TypeRef::BOOLEAN.into()
    }
}

impl InputTypeName for bool {}

impl OutputTypeName for bool {}

impl Register for f32 {}
impl TypeName for f32 {
    fn get_type_name() -> Cow<'static, str> {
        dynamic::TypeRef::FLOAT.into()
    }
}

impl InputTypeName for f32 {}

impl OutputTypeName for f32 {}

impl Register for f64 {}
impl TypeName for f64 {
    fn get_type_name() -> Cow<'static, str> {
        dynamic::TypeRef::FLOAT.into()
    }
}

impl InputTypeName for f64 {}

impl OutputTypeName for f64 {}

macro_rules! int_output_value {
    ($($t:ty),*) => {
        $(
            impl Register for $t {}
            impl TypeName for $t {
                fn get_type_name() -> Cow<'static, str> {
                    dynamic::TypeRef::INT.into()
                }
            }
            impl InputTypeName for $t {}
            impl OutputTypeName for $t {}
        )*
    };
}

int_output_value!(i8, i16, i32, i64, isize, u8, u16, u32, u64, usize);

impl<T> Register for Option<T>
where
    T: Register + 'static,
{
    fn register(registry: Registry) -> Registry {
        registry.register::<T>()
    }
}
impl<T> Register for MaybeUndefined<T>
where
    T: Register + 'static,
{
    fn register(registry: Registry) -> Registry {
        registry.register::<T>()
    }
}
impl<T, E> Register for Result<T, E>
where
    T: Register + 'static,
{
    fn register(registry: Registry) -> Registry {
        registry.register::<T>()
    }
}
impl<T> Register for Vec<T>
where
    T: Register + 'static,
{
    fn register(registry: Registry) -> Registry {
        registry.register::<T>()
    }
}
impl<T> Register for &[T]
where
    T: Register + 'static,
{
    fn register(registry: Registry) -> Registry {
        registry.register::<T>()
    }
}

impl<T, E> GetOutputTypeRef for Result<T, E>
where
    T: GetOutputTypeRef,
{
    #[inline]
    fn get_output_type_ref() -> TypeRefBuilder {
        T::get_output_type_ref()
    }
}

impl<T: OutputTypeName> GetOutputTypeRef for T {
    #[inline]
    fn get_output_type_ref() -> TypeRefBuilder {
        TypeRefBuilder::NamedNN(T::get_output_type_name().to_string())
    }
}

impl<T: GetOutputTypeRef> GetOutputTypeRef for Option<T> {
    #[inline]
    fn get_output_type_ref() -> TypeRefBuilder {
        let t = T::get_output_type_ref();
        t.optional()
    }
}

impl<T: GetOutputTypeRef> GetOutputTypeRef for Vec<T> {
    #[inline]
    fn get_output_type_ref() -> TypeRefBuilder {
        T::get_output_type_ref().list()
    }
}

impl<T: GetOutputTypeRef> GetOutputTypeRef for &[T] {
    #[inline]
    fn get_output_type_ref() -> TypeRefBuilder {
        T::get_output_type_ref().list()
    }
}

impl<T: InputTypeName> GetInputTypeRef for T {
    #[inline]
    fn get_input_type_ref() -> TypeRefBuilder {
        TypeRefBuilder::NamedNN(T::get_input_type_name().to_string())
    }
}

impl<T: GetInputTypeRef, E> GetInputTypeRef for Result<T, E> {
    #[inline]
    fn get_input_type_ref() -> TypeRefBuilder {
        T::get_input_type_ref().optional()
    }
}

impl<T: GetInputTypeRef> GetInputTypeRef for Option<T> {
    #[inline]
    fn get_input_type_ref() -> TypeRefBuilder {
        T::get_input_type_ref().optional()
    }
}

impl<T: GetInputTypeRef> GetInputTypeRef for MaybeUndefined<T> {
    #[inline]
    fn get_input_type_ref() -> TypeRefBuilder {
        T::get_input_type_ref().optional()
    }
}

impl<T: GetInputTypeRef> GetInputTypeRef for Vec<T> {
    #[inline]
    fn get_input_type_ref() -> TypeRefBuilder {
        T::get_input_type_ref().list()
    }
}
impl<T: GetInputTypeRef> GetInputTypeRef for &[T] {
    #[inline]
    fn get_input_type_ref() -> TypeRefBuilder {
        T::get_input_type_ref().list()
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_get_output_type_ref() {
        let type_ref: dynamic::TypeRef = <String as GetOutputTypeRef>::get_output_type_ref().into();
        assert_eq!(type_ref.to_string(), "String!");
        let type_ref: dynamic::TypeRef =
            <Option<String> as GetOutputTypeRef>::get_output_type_ref().into();
        assert_eq!(type_ref.to_string(), "String");
        let type_ref: dynamic::TypeRef =
            <Vec<String> as GetOutputTypeRef>::get_output_type_ref().into();
        assert_eq!(type_ref.to_string(), "[String!]!");
        let type_ref: dynamic::TypeRef =
            <Option<Vec<String>> as GetOutputTypeRef>::get_output_type_ref().into();
        assert_eq!(type_ref.to_string(), "[String!]");
        let type_ref: dynamic::TypeRef =
            <Vec<Option<String>> as GetOutputTypeRef>::get_output_type_ref().into();
        assert_eq!(type_ref.to_string(), "[String]!");
        let type_ref: dynamic::TypeRef =
            <Option<Vec<Option<String>>> as GetOutputTypeRef>::get_output_type_ref().into();
        assert_eq!(type_ref.to_string(), "[String]");
        let type_ref: dynamic::TypeRef =
            <&[String] as GetOutputTypeRef>::get_output_type_ref().into();
        assert_eq!(type_ref.to_string(), "[String!]!");
        let type_ref: dynamic::TypeRef =
            <Option<&[String]> as GetOutputTypeRef>::get_output_type_ref().into();
        assert_eq!(type_ref.to_string(), "[String!]");
        let type_ref: dynamic::TypeRef =
            <&[Option<String>] as GetOutputTypeRef>::get_output_type_ref().into();
        assert_eq!(type_ref.to_string(), "[String]!");
        let type_ref: dynamic::TypeRef =
            <Option<&[Option<String>]> as GetOutputTypeRef>::get_output_type_ref().into();
        assert_eq!(type_ref.to_string(), "[String]");
    }

    #[test]
    fn test_get_input_type_ref() {
        let type_ref: dynamic::TypeRef = <String as GetInputTypeRef>::get_input_type_ref().into();
        assert_eq!(type_ref.to_string(), "String!");
        let type_ref: dynamic::TypeRef =
            <Option<String> as GetInputTypeRef>::get_input_type_ref().into();
        assert_eq!(type_ref.to_string(), "String");
        let type_ref: dynamic::TypeRef =
            <Vec<String> as GetInputTypeRef>::get_input_type_ref().into();
        assert_eq!(type_ref.to_string(), "[String!]!");
        let type_ref: dynamic::TypeRef =
            <Option<Vec<String>> as GetInputTypeRef>::get_input_type_ref().into();
        assert_eq!(type_ref.to_string(), "[String!]");
        let type_ref: dynamic::TypeRef =
            <Vec<Option<String>> as GetInputTypeRef>::get_input_type_ref().into();
        assert_eq!(type_ref.to_string(), "[String]!");
        let type_ref: dynamic::TypeRef =
            <Option<Vec<Option<String>>> as GetInputTypeRef>::get_input_type_ref().into();
        assert_eq!(type_ref.to_string(), "[String]");
        let type_ref: dynamic::TypeRef =
            <&[String] as GetInputTypeRef>::get_input_type_ref().into();
        assert_eq!(type_ref.to_string(), "[String!]!");
        let type_ref: dynamic::TypeRef =
            <Option<&[String]> as GetInputTypeRef>::get_input_type_ref().into();
        assert_eq!(type_ref.to_string(), "[String!]");
        let type_ref: dynamic::TypeRef =
            <&[Option<String>] as GetInputTypeRef>::get_input_type_ref().into();
        assert_eq!(type_ref.to_string(), "[String]!");
        let type_ref: dynamic::TypeRef =
            <Option<&[Option<String>]> as GetInputTypeRef>::get_input_type_ref().into();
        assert_eq!(type_ref.to_string(), "[String]");
    }
}