worktable_macros 0.9.0

Proc-macro companion crate for worktable: the worktable! macro and its derives. Formerly published as worktable_codegen.
Documentation
mod impls;
mod index_fns;
mod select_executor;

use proc_macro2::TokenStream;
use quote::quote;

use crate::common::name_generator::{WorktableNameGenerator, is_unsized_vec};
use crate::generators::read_only::ReadOnlyGenerator;

impl ReadOnlyGenerator {
    pub fn gen_table_def(&mut self) -> syn::Result<TokenStream> {
        let page_size_consts = self.gen_page_size_consts();
        let version_const = self.gen_version_const();
        let type_ = self.gen_table_type();
        let impl_ = self.gen_table_impl();
        let index_fns = self.gen_table_index_fns()?;
        let select_query_executor_impl = self.gen_table_select_query_executor_impl();
        let column_range_type = self.gen_table_column_range_type();

        Ok(quote! {
            #page_size_consts
            #version_const
            #type_
            #impl_
            #index_fns
            #select_query_executor_impl
            #column_range_type
        })
    }

    fn gen_page_size_consts(&self) -> TokenStream {
        let name_generator = WorktableNameGenerator::from_table_name(self.name.to_string());
        let page_const_name = name_generator.get_page_size_const_ident();
        let inner_const_name = name_generator.get_page_inner_size_const_ident();

        quote! {
            const #page_const_name: usize = PAGE_SIZE;
            const #inner_const_name: usize = #page_const_name - GENERAL_HEADER_SIZE;
        }
    }

    fn gen_version_const(&self) -> TokenStream {
        let name_generator = WorktableNameGenerator::from_table_name(self.name.to_string());
        let version_const_name = name_generator.get_version_const_ident();
        let version = self.version;

        quote! {
            const #version_const_name: u32 = #version;
        }
    }

    fn gen_table_type(&self) -> TokenStream {
        let name_generator = WorktableNameGenerator::from_table_name(self.name.to_string());
        let ident = name_generator.get_work_table_ident();
        let row_type = name_generator.get_row_type_ident();
        let primary_key_type = name_generator.get_primary_key_type_ident();
        let index_type = name_generator.get_index_type_ident();
        let inner_const_name = name_generator.get_page_inner_size_const_ident();
        let avt_type_ident = name_generator.get_available_type_ident();
        let avt_index_ident = name_generator.get_available_indexes_ident();
        let lock_ident = name_generator.get_lock_type_ident();

        let pk_types = &self
            .columns
            .primary_keys
            .iter()
            .map(|i| {
                self.columns
                    .columns_map
                    .get(i)
                    .expect("should exist as got from definition")
                    .to_string()
            })
            .collect::<Vec<_>>();
        let pk_types_unsized = is_unsized_vec(pk_types);

        let derive = if pk_types_unsized {
            quote! {
                #[derive(Debug, PersistTable)]
                #[table(pk_unsized)]
            }
        } else {
            quote! {
                #[derive(Debug, PersistTable)]
                #[table(read_only)]
            }
        };

        let node_type = if pk_types_unsized {
            quote! {
                UnsizedNode<IndexPair<#primary_key_type, OffsetEqLink<#inner_const_name>>>
            }
        } else {
            quote! {
                Vec<IndexPair<#primary_key_type, OffsetEqLink<#inner_const_name>>>
            }
        };

        quote! {
            #derive
            pub struct #ident(
                WorkTable<
                    #row_type,
                    #primary_key_type,
                    #avt_type_ident,
                    #avt_index_ident,
                    #index_type,
                    #lock_ident,
                    <#primary_key_type as TablePrimaryKey>::Generator,
                    #inner_const_name,
                    #node_type
                >
            );
        }
    }
}