The Problem statement:
GIve a ty: &str
and matching it to an Enum, how do I ensure I didn't miss a match arm if I am adding a new variant in GraphqlNode
// the `Model`s cannot implement Default
// and thus cannot use strum::EnumIter
#[derive(async_graphql::Interface)]
enum Node {
Brand(brand::Model),
Category(category::Model),
// Add a new varaiant
// New(new::Model)
}
fn work(ty: &str, id: i64) {
// match the `ty` to a variant
match ty {
"Brand" => brand::Model.fetch(id),
"Category" => category::Model.fetch(id),
// also remember to add the new type here too
// "New" => new::Model.fetch(id),
_ => panic!("unknown type"),
}
}
The Solution
I asked for help on Discord and this is the approach I am working on. Using the graphql_node
macro rule to ensure the match.
mod brand {
pub struct Model;
}
macro_rules! graphql_node {
{
$(($variant_name:ident, $p:path),)*
} => {
use async_graphql::Interface;
#[derive(Interface)]
enum Node {
$($variant_name($p),)*
// the above is expand to below
// Brand(brand::Model),
}
fn work(ty: &str, id: i64) {
$(const $variant_name: &str = stringify!($variant_name);)*
match ty {
// Now I won't miss any match
$($variant_name => $module::Model.fetch(id),)*
_ => panic!("unknown type"),
}
}
}
}
graphql_node! {
(Brand, brand::Model),
}
The Error
I thought I am using the right designator, $p:path
, in my macro_rule and it turned out async_graphql
is not happy about it on this line because it is expecting a Type::Path(p)
error: Invalid type
--> src/main.rs:13:29
|
13 | $($variant_name($p),)*
| ^^
Naively, I tried to print out $ty
in async_graphql
and see what type it actually was.
[async-graphql/derive/src/interface.rs:97:9] &ty = Type::Group {
group_token: Group,
elem: Type::Path {
qself: None,
path: Path {
leading_colon: None,
segments: [
PathSegment {
ident: Ident {
ident: "brand",
span: #0 bytes(378..383),
},
arguments: PathArguments::None,
},
PathSep,
PathSegment {
ident: Ident {
ident: "Model",
span: #0 bytes(385..390),
},
arguments: PathArguments::None,
},
],
},
},
}
And at this moment I am totally lost as I am not that confident in writing/reading macros.
Questions
- Is there a way to print out the fully qualiified name of a type? I couldn't find what
Type::Group
was, I checkedsyn
,quote
andproc_macro2
and couldn't find an exact match. - I specified
$p:path
but when it reached toasync_graphql
, it became aType::Group
? How do I fix it?