worktable_macros 0.9.0

Proc-macro companion crate for worktable: the worktable! macro and its derives. Formerly published as worktable_codegen.
Documentation
use proc_macro2::TokenStream;
use quote::quote;

use crate::common::name_generator::WorktableNameGenerator;
use crate::generators::read_only::ReadOnlyGenerator;

impl ReadOnlyGenerator {
    pub fn gen_secondary_index_info_impl_def(&mut self) -> TokenStream {
        let name_generator = WorktableNameGenerator::from_table_name(self.name.to_string());
        let index_type_ident = name_generator.get_index_type_ident();

        let info_fn = self.gen_index_info_fn();
        let is_empty_fn = self.gen_index_is_empty_fn();

        quote! {
            impl TableSecondaryIndexInfo for #index_type_ident {
                #info_fn
                #is_empty_fn
            }
        }
    }

    fn gen_index_info_fn(&self) -> TokenStream {
        let rows = self.columns.indexes.values().map(|idx| {
            let index_field_name = &idx.name;
            let index_name_str = index_field_name.to_string();

            if idx.is_unique {
                quote! {
                    info.push(IndexInfo {
                        name: #index_name_str.to_string(),
                        index_type: IndexKind::Unique,
                        key_count: self.#index_field_name.len(),
                        capacity: self.#index_field_name.capacity(),
                        heap_size: self.#index_field_name.heap_size(),
                        used_size: self.#index_field_name.used_size(),
                        node_count: self.#index_field_name.node_count(),
                    });
                }
            } else {
                quote! {
                    info.push(IndexInfo {
                        name: #index_name_str.to_string(),
                        index_type: IndexKind::NonUnique,
                        key_count: self.#index_field_name.len(),
                        capacity: self.#index_field_name.capacity(),
                        heap_size: self.#index_field_name.heap_size(),
                        used_size: self.#index_field_name.used_size(),
                        node_count: self.#index_field_name.node_count(),
                    });
                }
            }
        });

        quote! {
            fn index_info(&self) -> Vec<IndexInfo> {
                let mut info = Vec::new();
                #(#rows)*
                info
            }
        }
    }

    fn gen_index_is_empty_fn(&self) -> TokenStream {
        let is_empty = self
            .columns
            .indexes
            .values()
            .map(|idx| {
                let index_field_name = &idx.name;
                quote! {
                    self.#index_field_name.len() == 0
                }
            })
            .collect::<Vec<_>>();

        if is_empty.is_empty() {
            quote! {
                fn is_empty(&self) -> bool {
                    true
                }
            }
        } else {
            quote! {
                fn is_empty(&self) -> bool {
                    #(#is_empty) &&*
                }
            }
        }
    }
}