enum_dispatch/
enum_dispatch_variant.rs1use std::iter::FromIterator;
9
10use quote::TokenStreamExt;
11
12use crate::filter_attrs::FilterAttrs;
13
14#[derive(Clone)]
16pub struct EnumDispatchVariant {
17 pub attrs: Vec<syn::Attribute>,
18 pub ident: syn::Ident,
19 pub field_attrs: Vec<syn::Attribute>,
20 pub ty: syn::Type,
21}
22
23impl syn::parse::Parse for EnumDispatchVariant {
25 fn parse(input: syn::parse::ParseStream) -> syn::parse::Result<Self> {
26 let attrs = input.call(syn::Attribute::parse_outer)?;
27 let ident: syn::Ident = input.parse()?;
28 let (field_attrs, ty) = if input.peek(syn::token::Brace) {
29 unimplemented!("enum_dispatch variants cannot have braces for arguments");
30 } else if input.peek(syn::token::Paren) {
31 let input: syn::FieldsUnnamed = input.parse()?;
32 let mut fields = input.unnamed.iter();
33 let field_1 = fields
34 .next()
35 .expect("Named enum_dispatch variants must have one unnamed field");
36 if fields.next().is_some() {
37 panic!("Named enum_dispatch variants can only have one unnamed field");
38 }
39 (field_1.attrs.clone(), field_1.ty.clone())
40 } else {
41 (vec![], into_type(ident.clone()))
42 };
43 Ok(EnumDispatchVariant {
44 attrs,
45 ident,
46 field_attrs,
47 ty,
48 })
49 }
50}
51
52impl quote::ToTokens for EnumDispatchVariant {
54 fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
55 tokens.append_all(self.attrs.outer());
56 self.ident.to_tokens(tokens);
57 syn::token::Paren::default().surround(tokens, |tokens| {
58 tokens.append_all(self.field_attrs.iter());
59 self.ty.to_tokens(tokens);
60 });
61 }
62}
63
64fn into_type(ident: syn::Ident) -> syn::Type {
72 syn::Type::Path(syn::TypePath {
73 path: syn::Path {
74 leading_colon: None,
75 segments: syn::punctuated::Punctuated::from_iter(vec![syn::PathSegment {
76 arguments: syn::PathArguments::None,
77 ident,
78 }]),
79 },
80 qself: None,
81 })
82}