use std::iter::FromIterator;
use quote::TokenStreamExt;
use crate::filter_attrs::FilterAttrs;
#[derive(Clone)]
pub struct EnumDispatchVariant {
pub attrs: Vec<syn::Attribute>,
pub ident: syn::Ident,
pub field_attrs: Vec<syn::Attribute>,
pub ty: syn::Type,
}
impl syn::parse::Parse for EnumDispatchVariant {
fn parse(input: syn::parse::ParseStream) -> syn::parse::Result<Self> {
let attrs = input.call(syn::Attribute::parse_outer)?;
let ident: syn::Ident = input.parse()?;
let (field_attrs, ty) = if input.peek(syn::token::Brace) {
unimplemented!("enum_dispatch variants cannot have braces for arguments");
} else if input.peek(syn::token::Paren) {
let input: syn::FieldsUnnamed = input.parse()?;
let mut fields = input.unnamed.iter();
let field_1 = fields
.next()
.expect("Named enum_dispatch variants must have one unnamed field");
if fields.next().is_some() {
panic!("Named enum_dispatch variants can only have one unnamed field");
}
(field_1.attrs.clone(), field_1.ty.clone())
} else {
(vec![], into_type(ident.clone()))
};
Ok(EnumDispatchVariant {
attrs,
ident,
field_attrs,
ty,
})
}
}
impl quote::ToTokens for EnumDispatchVariant {
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
tokens.append_all(self.attrs.outer());
self.ident.to_tokens(tokens);
syn::token::Paren::default().surround(tokens, |tokens| {
tokens.append_all(self.field_attrs.iter());
self.ty.to_tokens(tokens);
});
}
}
fn into_type(ident: syn::Ident) -> syn::Type {
syn::Type::Path(syn::TypePath {
path: syn::Path {
leading_colon: None,
segments: syn::punctuated::Punctuated::from_iter(vec![syn::PathSegment {
arguments: syn::PathArguments::None,
ident,
}]),
},
qself: None,
})
}