nesting 0.1.1

Nesting structs, enums, and impls, in Rust!
Documentation
use super::*;

pub struct StructDef {
    pub kind: StructKind,
    pub attrs: Vec<Attribute>,
    pub vis: Visibility,
    pub name: Ident,
    pub fields: Vec<FieldDef>,
    pub nested_items: Vec<ItemDef>,
}

impl Parse for StructDef {
    fn parse(input: ParseStream) -> Result<Self> {
        let attrs = input.call(Attribute::parse_outer)?;
        let vis = input.parse::<Visibility>()?;
        input.parse::<Token![struct]>()?;

        let name = input.parse::<Ident>()?;

        let mut nested_items: Vec<ItemDef> = Vec::new();

        // Tuple structs
        if input.peek(syn::token::Paren) {
            let kind = StructKind::TupleStruct;

            let content;
            syn::parenthesized!(content in input);

            let mut fields = Vec::new();

            while !content.is_empty() {
                let attrs = content.call(Attribute::parse_outer)?;
                let vis = content.parse::<Visibility>()?;
                let ty = content.parse::<Type>()?;
                let name = Ident::new(&format!("_{}", fields.len()), ty.span());

                fields.push(FieldDef {
                    attrs,
                    vis,
                    name,
                    ty,
                });

                if content.peek(Token![,]) {
                    content.parse::<Token![,]>()?;
                }
            }

            input.parse::<Token![;]>()?;

            return Ok(Self {
                kind,
                attrs,
                vis,
                name,
                fields,
                nested_items,
            });
        }

        // Field structs
        if input.peek(syn::token::Brace) {
            let kind = StructKind::FieldStruct;

            let content;
            syn::braced!(content in input);

            let mut fields = 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);

                    // Optional trailing comma
                    if content.peek(Token![,]) {
                        content.parse::<Token![,]>()?;
                    }
                    continue;
                }

                let is_field = {
                    let lookahead = content.fork();
                    lookahead.call(Attribute::parse_outer).is_ok()
                        && lookahead.parse::<Visibility>().is_ok()
                        && lookahead.parse::<Ident>().is_ok()
                        && lookahead.peek(Token![:])
                };

                if is_field {
                    let attrs = content.call(Attribute::parse_outer)?;
                    let vis = content.parse::<Visibility>()?;
                    let name = content.parse::<Ident>()?;
                    content.parse::<Token![:]>()?;
                    let ty = content.parse::<Type>()?;

                    fields.push(FieldDef {
                        attrs,
                        vis,
                        name,
                        ty,
                    });

                    // Optional trailing commas
                    if content.peek(Token![,]) {
                        content.parse::<Token![,]>()?;
                    }

                    continue;
                }

                return Err(content.error("Expected field, struct, impl, or function"));
            }

            return Ok(Self {
                kind,
                attrs,
                vis,
                name,
                fields,
                nested_items,
            });
        }

        // Marker structs
        if input.peek(Token![;]) {
            let kind = StructKind::MarkerStruct;

            input.parse::<Token![;]>()?;

            return Ok(Self {
                kind,
                attrs,
                vis,
                name,
                fields: Vec::new(),
                nested_items,
            });
        }

        return Err(input.error("Expected a valid struct"));
    }
}

pub enum StructKind {
    FieldStruct,
    TupleStruct,
    MarkerStruct,
}