af_path 0.2.3

path查询语言库
Documentation
//#![feature(min_type_alias_impl_trait)]

extern crate serde_json;
extern crate serde_yaml;

mod expression;
mod tables;
mod structs;
mod token;
mod program;
mod json;
mod base;

use std::rc::Rc;

use proc_macro::{TokenStream};
use syn::__private::TokenStream2;
use core::iter::Iterator;
use proc_macro;
use std::{collections::BTreeMap, fs::File};
use std::fs; 
use token::Tokens;
use program::parse;
use json::{tables_iter};
use std::collections::HashMap;

use expression::{Type, to_exp};

#[macro_use]
extern crate quote;

// 根据json配置文件产生数据库表到全局定义
#[proc_macro]
pub fn tables(_input: TokenStream) -> TokenStream {
    let gen = tables::tables(&tables_def());
    TokenStream::from(gen)
}

// 根据json配置,产生表结构定义,每个表产生一个struct结构
#[proc_macro]
pub fn structs(_input: TokenStream) -> TokenStream {
    let gen = structs::structs(&tables_def());
    TokenStream::from(gen)
}

// 读取所有查询内容,编译成根据名称调用的过程
#[proc_macro]
pub fn path(_input: TokenStream) -> TokenStream {
    // 获取数据库表定义内容
    let tables_def = tables_def();

    let dir = path_config();
    // 读取文件夹query下的所有查询
    let gen: TokenStream2 = dir.iter().map(|(file_name, file_path)| {
        // 读取文件,解析成token流,给单个解析过程处理
        let str = fs::read_to_string(&file_path).expect(&format!("文件找不到: {}", &file_path));
        let stream: TokenStream = str.parse().expect(&format!("文件继续错误: {}", &file_path));
        let mut tokens = Tokens::new(stream);

        let mut funcs = Vec::new();
        // 对token流进行解析,产生一条查询语句
        let ast = parse(&mut tokens, &mut funcs).expect(&format!("{}", &file_path));

        let mut funcs_type = to_func_type(&funcs);
        let (one_path, _, _) = to_exp(&ast, &mut funcs_type, None, &tables_def);

        // 产生一项匹配结果
        quote! {
            #file_name => Ok({#one_path}),
        }
    })
    //.inspect(|x| println!("{}", x.to_string()))
    .collect();

    // 添加上match语句部分
    let gen = quote! {
        unsafe {
            match name {
                #gen
                _ => Err(format!("不认识的查询:{}", name))
            }    
        }
    };

    TokenStream::from(gen)
}

// 根据传过来的表名,产生一条记录,并插入表中
#[proc_macro]
pub fn insert_data(_input: TokenStream) -> TokenStream {
    // 对每一个要加载数据对数据库表,产生根据名称转换实体,并插入表中的代码
    let config = config();
    let map = tables_iter(&config);
    let gen = map.iter().map(|(table_name, _)| {
        let name: syn::Ident = syn::parse_str(table_name).expect(&format!("表名不合法, {}", table_name));
        quote! {
            // 把json对象转换成rust结构体
            #table_name => {
                let e: entity::#name = entity::#name::new_test(&json_data);
                unsafe {
                    database::DATABASE.#name.add_data(e);
                }
            },
        }
    }).collect::<TokenStream2>();

    let gen = quote! {
        match table_name.as_str() { 
            #gen
            _ => panic!("没有这个表,{:?}", table_name)
        }
    };

    TokenStream::from(gen)
}

// 加载一条测试数据
#[proc_macro]
pub fn insert_test(_input: TokenStream) -> TokenStream {
    // 对每一个要加载数据对数据库表,产生根据名称转换实体,并插入表中的代码
    let config = config();
    let map = tables_iter(&config);
    let gen = map.iter().map(|(table_name, _)| {
        let name: syn::Ident = syn::parse_str(table_name).expect(&format!("表名不合法, {}", table_name));
        quote! {
            // 把json对象转换成rust结构体
            #table_name => {
                let e: entity::#name = entity::#name::new_test(&json_data);
                unsafe {
                    database::DATABASE.#name.add_test(e, |x, key, entity_op| {
                        // 执行x,把主键保存下来,把变化的实体保存下来
                        x();
                        //#key_name.push(key);
                        // 把变化的实体保存下来
                        //if let Some(entity) = entity_op {
                        //    #entity_name.push(entity);
                        //}
                    });
                }
            },
        }
    }).collect::<TokenStream2>();

    let gen = quote! {
        match table_name.as_str() { 
            #gen
            _ => panic!("没有这个表,{:?}", table_name)
        }
    };

    TokenStream::from(gen)
}

// 打开数据库配置文件,获得json格式配置结果
fn config() -> serde_json::Value {
    // 加载表结构配置文件
    let f = File::open("tables.json").expect("文件tables.json不存在");
    serde_json::from_reader(f).expect("文件tables.json格式错误")
}

// 获得所有表的定义内容
fn tables_def() -> HashMap<String, json::Table> {
    let config = config();
    match json::tables_def(&config) {
        Ok(v) => v,
        Err(err) => panic!("tables.json文件有错误,{:?}", err)
    }
}

// 加载path的配置
fn path_config() -> BTreeMap<String, String> {
    let f = File::open("path.yaml").expect("文件path.yaml不存在");
    let result: BTreeMap<String, String> = serde_yaml::from_reader(f).expect("文件path.yaml格式错误");
    result
}

// 把定义的函数转换成函数及返回类型值,返回类型先按未知处理,在转换时,可以知道实际类型
fn to_func_type(del: &Vec<String>) -> HashMap<String, Rc<Type<'static>>> {
    let mut result = HashMap::new();
    for v in del {
        result.insert(v.to_string(), Rc::new(Type::Unknown));
    }
    result
}