atruct 0.3.2

macros for anonymous structs in Rust
Documentation
use proc_macro2::TokenStream;
use quote::{quote, format_ident};
use super::interpreter::{StructMap, Item};


pub fn build_token_stream(structs: StructMap) -> TokenStream {
    let defs = build_struct_defs(structs.clone());
    let instance = build_struct_instance(structs);

    quote!({
        #defs
        #instance
    })
}

fn build_struct_defs(structs: StructMap) -> TokenStream {
    let mut defs = TokenStream::new();

    for (id, s) in structs {
        let wrapping_name = if &id == "0" {quote!(Atruct)} else {wrapping_name(&id)};

        let mut field_defs = TokenStream::new();
        for (ident, item) in s.fields() {
            let type_name = item.type_name();
            field_defs.extend(quote!(#ident: #type_name, ));
        }
        defs.extend(quote!(
            struct #wrapping_name {#field_defs}
        ));
    }

    defs
}

fn build_struct_instance(structs: StructMap) -> TokenStream {
    build_struct_instance_inner(&structs, &"0".to_owned(), &mut TokenStream::new())
}
fn build_struct_instance_inner(
    structs: &StructMap,
    id: &String,
    current_instance: &mut TokenStream
) -> TokenStream {
    let wrapping_name = if id == "0" {quote!(Atruct)} else {wrapping_name(id)};

    let mut fields = TokenStream::new();
    let target = structs.get(id);
    for (name, item) in target.fields() {
        fields.extend(quote!(#name: ));
        match item {
            Item::Struct(next_id) => {
                let next_struct = build_struct_instance_inner(
                    structs, next_id, current_instance
                );
                fields.extend(quote!(#next_struct, ))
            }
            Item::Value {
                #[allow(unused)]
                type_of_value,
                value,
            } => {
                fields.extend(quote!(#value, ))
            }
        }
    }

    quote!(#wrapping_name {#fields})
}

pub fn wrapping_name(id: &String) -> TokenStream {
    let name = format_ident!("S_{}", id.clone());
    quote!(#name)
}