dynamic-graphql-derive 0.10.2

Dynamic GraphQL schema macro
Documentation
#![allow(dead_code)]

use std::ops::Deref;

use darling::FromDeriveInput;
use darling::FromField;
use darling::FromVariant;
use darling::util::Ignored;
use syn::DeriveInput;

use crate::utils::impl_block::FromFnArg;
use crate::utils::impl_block::FromImplItemFn;
use crate::utils::impl_block::FromItemImpl;
use crate::utils::impl_block::FromItemTrait;
use crate::utils::impl_block::FromTraitItemFn;
use crate::utils::with_context::SetContext;
use crate::utils::with_index::SetIndex;

pub trait SetArg<Arg> {
    type Output: Sized;
    fn with_arg(self, arg: Arg) -> Self::Output;
}

impl<T, E, A> SetArg<A> for Result<T, E>
where
    T: SetArg<A>,
{
    type Output = Result<T::Output, E>;

    fn with_arg(self, arg: A) -> Self::Output {
        self.map(|t| t.with_arg(arg))
    }
}

pub struct WithArg<Arg, D> {
    pub arg: Arg,
    pub inner: D,
}

impl<D, Arg> Deref for WithArg<Arg, D> {
    type Target = D;

    fn deref(&self) -> &Self::Target {
        &self.inner
    }
}

impl<D, Arg> SetArg<Arg> for WithArg<Ignored, D> {
    type Output = WithArg<Arg, D>;

    fn with_arg(self, arg: Arg) -> Self::Output {
        WithArg {
            arg,
            inner: self.inner,
        }
    }
}

macro_rules! impl_for_with_arg {
    ($trayt:ident, $method:ident, $syn:path) => {
        impl<D: $trayt> $trayt for WithArg<Ignored, D> {
            fn $method(input: &$syn) -> darling::Result<Self> {
                let inner = D::$method(input)?;
                Ok(WithArg {
                    arg: Ignored,
                    inner,
                })
            }
        }
    };
}

macro_rules! impl_mut_for_with_arg {
    ($trayt:ident, $method:ident, $syn:path) => {
        impl<D: $trayt> $trayt for WithArg<Ignored, D> {
            fn $method(input: &mut $syn) -> darling::Result<Self> {
                let inner = D::$method(input)?;
                Ok(WithArg {
                    arg: Ignored,
                    inner,
                })
            }
        }
    };
}

impl_for_with_arg!(FromDeriveInput, from_derive_input, DeriveInput);
impl_for_with_arg!(FromField, from_field, syn::Field);
impl_for_with_arg!(FromVariant, from_variant, syn::Variant);

impl_mut_for_with_arg!(FromFnArg, from_fn_arg, syn::FnArg);
impl_mut_for_with_arg!(FromImplItemFn, from_impl_item_method, syn::ImplItemFn);
impl_mut_for_with_arg!(FromItemImpl, from_item_impl, syn::ItemImpl);
impl_mut_for_with_arg!(FromItemTrait, from_item_trait, syn::ItemTrait);
impl_mut_for_with_arg!(FromTraitItemFn, from_trait_item_method, syn::TraitItemFn);

impl<A, D: SetIndex> SetIndex for WithArg<A, D> {
    fn with_index(self, index: usize) -> Self {
        WithArg {
            arg: self.arg,
            inner: self.inner.with_index(index),
        }
    }
}

impl<A, D: SetContext> SetContext for WithArg<A, D> {
    type Context = D::Context;

    fn set_context(&mut self, context: Self::Context) {
        self.inner.set_context(context);
    }
}