#[macro_export(local_inner_macros)]
macro_rules! graphql_union {
( @as_item, $i:item) => { $i };
( @as_expr, $e:expr) => { $e };
( @as_path, $p:path) => { $p };
( @as_type, $t:ty) => { $t };
(
@ gather_meta,
($reg:expr, $acc:expr, $descr:expr),
description : $value:tt $( $rest:tt )*
) => {
$descr = Some(graphql_interface!(@as_expr, $value));
graphql_union!(@ gather_meta, ($reg, $acc, $descr), $( $rest )*)
};
(
@ gather_meta,
($reg:expr, $acc:expr, $descr:expr),
instance_resolvers: | $ctxtvar:pat
| { $( $srctype:ty => $resolver:expr ),* $(,)* } $( $rest:tt )*
) => {
$acc = __graphql__vec![
$(
$reg.get_type::<$srctype>(&())
),*
];
graphql_union!(@ gather_meta, ($reg, $acc, $descr), $( $rest )*)
};
(
@ concrete_type_name,
($outname:tt, $ctxtarg:ident, $ctxttype:ty),
instance_resolvers: | $ctxtvar:pat
| { $( $srctype:ty => $resolver:expr ),* $(,)* } $( $rest:tt )*
) => {
let $ctxtvar = &$ctxtarg;
$(
if let Some(_) = $resolver as Option<$srctype> {
return (<$srctype as $crate::GraphQLType>::name(&())).unwrap().to_owned();
}
)*
__graphql__panic!("Concrete type not handled by instance resolvers on {}", $outname);
};
(
@ resolve_into_type,
($outname:tt, $typenamearg:ident, $execarg:ident, $ctxttype:ty),
instance_resolvers: | $ctxtvar:pat
| { $( $srctype:ty => $resolver:expr ),* $(,)* } $( $rest:tt )*
) => {
let $ctxtvar = &$execarg.context();
$(
if $typenamearg == (<$srctype as $crate::GraphQLType>::name(&())).unwrap().to_owned() {
return $execarg.resolve(&(), &$resolver);
}
)*
__graphql__panic!("Concrete type not handled by instance resolvers on {}", $outname);
};
( @ $mfn:ident, $args:tt, , $($rest:tt)* ) => {
graphql_union!(@ $mfn, $args, $($rest)*);
};
( @ $mfn:ident, $args:tt, $item:tt $($rest:tt)* ) => {
graphql_union!(@ $mfn, $args, $($rest)*);
};
( @ $mfn:ident, $args:tt, ) => {};
(
( $($lifetime:tt),* ) $name:ty : $ctxt:ty as $outname:tt | &$mainself:ident | {
$( $items:tt )*
}
) => {
graphql_union!(@as_item, impl<$($lifetime)*> $crate::GraphQLType for $name {
type Context = $ctxt;
type TypeInfo = ();
fn name(_: &()) -> Option<&str> {
Some($outname)
}
#[allow(unused_assignments)]
#[allow(unused_mut)]
fn meta<'r>(_: &(), registry: &mut $crate::Registry<'r>) -> $crate::meta::MetaType<'r> {
let mut types;
let mut description = None;
graphql_union!(@ gather_meta, (registry, types, description), $($items)*);
let mut mt = registry.build_union_type::<$name>(&(), &types);
if let Some(description) = description {
mt = mt.description(description);
}
mt.into_meta()
}
fn concrete_type_name(&$mainself, context: &Self::Context, _: &()) -> String {
graphql_union!(
@ concrete_type_name,
($outname, context, $ctxt),
$($items)*);
}
fn resolve_into_type(
&$mainself,
_: &(),
type_name: &str,
_: Option<&[$crate::Selection]>,
executor: &$crate::Executor<Self::Context>,
)
-> $crate::ExecutionResult
{
graphql_union!(
@ resolve_into_type,
($outname, type_name, executor, $ctxt),
$($items)*);
}
});
};
(
<$($lifetime:tt),*> $name:ty : $ctxt:ty as $outname:tt | &$mainself:ident | {
$( $items:tt )*
}
) => {
graphql_union!(
($($lifetime),*) $name : $ctxt as $outname | &$mainself | { $( $items )* });
};
(
$name:ty : $ctxt:ty as $outname:tt | &$mainself:ident | {
$( $items:tt )*
}
) => {
graphql_union!(() $name : $ctxt as $outname | &$mainself | { $( $items )* });
};
(
$name:ty : $ctxt:ty | &$mainself:ident | {
$( $items:tt )*
}
) => {
graphql_union!(() $name : $ctxt as (__graphql__stringify!($name)) | &$mainself | { $( $items )* });
};
}