use super::*;
pub struct EnumDef {
pub attrs: Vec<Attribute>,
pub vis: Visibility,
pub name: Ident,
pub variants: Vec<VariantDef>,
pub nested_items: Vec<ItemDef>,
}
impl Parse for EnumDef {
fn parse(input: ParseStream) -> Result<Self> {
let attrs = input.call(Attribute::parse_outer)?;
let vis = input.parse::<Visibility>()?;
input.parse::<Token![enum]>()?;
let name = input.parse::<Ident>()?;
let content;
syn::braced!(content in input);
let mut variants: Vec<VariantDef> = Vec::new();
let mut nested_items: Vec<ItemDef> = Vec::new();
while !content.is_empty() {
let is_nested_item = {
let lookahead = content.fork();
lookahead.call(Attribute::parse_outer).is_ok()
&& lookahead.parse::<Visibility>().is_ok()
&& lookahead.parse::<Option<Token![async]>>().is_ok()
&& (lookahead.peek(Token![struct])
|| lookahead.peek(Token![enum])
|| lookahead.peek(Token![impl])
|| lookahead.peek(Token![fn]))
};
if is_nested_item {
let mut result = content.parse()?;
match &mut result {
ItemDef::LooseFunc { func: _, parent } => {
*parent = Some(name.clone());
}
_ => {}
}
nested_items.push(result);
if content.peek(Token![,]) {
content.parse::<Token![,]>()?;
}
continue;
}
let attrs = content.call(Attribute::parse_outer)?;
let name = content.parse::<Ident>()?;
if content.peek(syn::token::Paren) {
let inner;
syn::parenthesized!(inner in content);
let mut fields = Vec::new();
while !inner.is_empty() {
let attrs = inner.call(Attribute::parse_outer)?;
let vis = inner.parse::<Visibility>()?;
let ty = inner.parse::<Type>()?;
let name = Ident::new(&format!("_{}", fields.len()), ty.span());
fields.push(FieldDef {
attrs,
vis,
ty,
name,
});
if inner.peek(Token![,]) {
inner.parse::<Token![,]>()?;
}
}
variants.push(VariantDef::Tuple(TupleVariant {
attrs,
name,
fields,
}));
if content.peek(Token![,]) {
content.parse::<Token![,]>()?;
}
continue;
}
if content.peek(syn::token::Brace) {
let inner;
syn::braced!(inner in content);
let mut fields = Vec::new();
while !inner.is_empty() {
let attrs = inner.call(Attribute::parse_outer)?;
let vis = inner.parse::<Visibility>()?;
let name = inner.parse::<Ident>()?;
inner.parse::<Token![:]>()?;
let ty = inner.parse::<Type>()?;
fields.push(FieldDef {
attrs,
vis,
name,
ty,
});
if inner.peek(Token![,]) {
inner.parse::<Token![,]>()?;
}
}
variants.push(VariantDef::Struct(StructVariant {
attrs,
name,
fields,
}));
if content.peek(Token![,]) {
content.parse::<Token![,]>()?;
}
continue;
}
variants.push(VariantDef::Unit(UnitVariant { attrs, name }));
if content.peek(Token![,]) {
content.parse::<Token![,]>()?;
}
}
if content.peek(Token![,]) {
content.parse::<Token![,]>()?;
}
Ok(EnumDef {
attrs,
name,
nested_items,
vis,
variants,
})
}
}
pub enum VariantDef {
Unit(UnitVariant),
Tuple(TupleVariant),
Struct(StructVariant),
}
pub struct UnitVariant {
pub attrs: Vec<Attribute>,
pub name: Ident,
}
pub struct TupleVariant {
pub attrs: Vec<Attribute>,
pub name: Ident,
pub fields: Vec<FieldDef>,
}
pub struct StructVariant {
pub attrs: Vec<Attribute>,
pub name: Ident,
pub fields: Vec<FieldDef>,
}