odra-codegen 0.7.1

Code generators for Odra IR.
Documentation
use derive_more::From;
use odra_ir::InstanceItem as IrInstanceItem;
use proc_macro2::TokenStream;
use quote::quote;
use syn::{punctuated::Punctuated, Field, Token};

use crate::GenerateCode;

#[derive(From)]
pub struct InstanceItem<'a> {
    item: &'a IrInstanceItem
}

impl GenerateCode for InstanceItem<'_> {
    fn generate_code(&self) -> proc_macro2::TokenStream {
        let ident = &self.item.ident();

        let static_fields: TokenStream = self
            .fields_iter()
            .flat_map(|field| {
                let ident = field.ident.as_ref().unwrap();
                quote!(let (#ident, keys) = odra::StaticInstance::instance(&keys);)
            })
            .collect();

        let init = self
            .fields_iter()
            .map(|field| {
                let ident = field.ident.as_ref().unwrap();
                quote!(#ident)
            })
            .collect::<Punctuated<TokenStream, Token![,]>>();

        let dynamic_fields = self
            .fields_iter()
            .map(|field| {
                let ident = field.ident.as_ref().unwrap();
                quote!(#ident: odra::DynamicInstance::instance(&[namespace, stringify!(#ident).as_bytes()].concat()))
            })
            .collect::<Punctuated<TokenStream, Token![,]>>();

        quote! {
            impl odra::StaticInstance for #ident {
                fn instance<'a>(keys: &'a [&'a str]) -> (Self, &'a [&'a str]) {
                    #static_fields
                    (
                        Self { #init },
                        keys
                    )
                }
            }

            impl odra::DynamicInstance for #ident {
                fn instance(namespace: &[u8]) -> Self {
                    Self {
                        #dynamic_fields
                    }
                }
            }
        }
    }
}

impl<'a> InstanceItem<'a> {
    fn fields_iter(&'a self) -> impl Iterator<Item = &'a Field> + 'a {
        self.item.data_struct().fields.iter()
    }
}