use syn::__private::TokenStream2;
use crate::json;
use crate::json::{Field};
use std::collections::HashMap;
pub fn structs(map: &HashMap<String, json::Table>) -> TokenStream2 {
map.iter().map(|(k, v)| {
let name: syn::Ident = syn::parse_str(&k).expect(&format!("表名不是合法变量, {}", &k));
let fields = create_fields_get(&v.fields, |field_name, ty| fields(field_name, ty));
let fields_get = create_fields_get(&v.fields, |field_name, ty| create_field_get(field_name, ty));
let fields_test = create_fields_get(&v.fields, |field_name, ty| create_field_test(field_name, ty));
let fields_clone = create_fields_get(&v.fields, |field_name, ty| create_field_clone(field_name, ty));
let record = create_fields_get(&v.fields, |field_name, _| create_record(field_name));
let copy = create_fields_get(&v.fields, |field_name, ty| create_copy(field_name, ty));
let key_name: syn::Ident = syn::parse_str(&v.key).expect("主键名不合法");
let key_type = key_type(&v);
let table_def = quote! {
#[derive(Debug)]
pub struct #name { #fields }
impl Entity<#key_type> for #name {
fn new(row: &MssqlRow) -> Self {
#fields_get
#name{#record}
}
fn key(&self) -> #key_type {
self.#key_name
}
fn put(self) -> ClosureType {
let update: ClosureType = Box::new(move || {
unsafe {DATABASE.#name.data.insert(self.#key_name, self)};
});
update
}
fn clone(&self) -> Self {
#fields_clone
#name{#record}
}
fn copy(key: &i32, other: Self) -> ClosureType {
let entity = unsafe {DATABASE.#name.data.get_mut(&key).expect("根据主键居然没找到数据")};
let update: ClosureType = Box::new(move || {
#copy
});
update
}
fn new_test(value: &HashMap<String, Value>) -> Self {
#fields_test
#name{#record}
}
}
};
table_def
}).collect()
}
fn key_type(table: &json::Table) -> TokenStream2 {
let key = &table.key;
let field = &table.fields[key.as_str()];
let result = field_type(&field);
result
}
fn fields(field_name: &str, field_attr: &Field) -> TokenStream2 {
let name: syn::Ident = syn::parse_str(&field_name).expect(&format!("字段名不是合法变量, {}", field_name));
let ty = field_type(field_attr);
quote! {
pub #name: #ty,
}
}
fn field_type(json: &Field) -> TokenStream2 {
match json {
Field::Int => quote! { i32 },
Field::String => quote! { String },
Field::Double => quote! { f64 },
Field::Datetime => quote! { i32 },
Field::OneToOne(entity, _) | Field::ManyToOne(entity, _) => {
let name: syn::Ident = syn::parse_str(&entity).expect(&format!("entity名称不合法, {:?}", entity));
quote! { Option<&'static #name> }
},
Field::OneToMany(entity, _) => {
let name: syn::Ident = syn::parse_str(&entity).expect(&format!("entity名称不合法, {:?}", entity));
quote! { Vec<&'static #name> }
},
}
}
fn create_fields_get<F>(fields: &HashMap<String, Field>, f: F) -> TokenStream2
where F: Fn(&str, &Field) -> TokenStream2 {
fields.iter().map(|(field_name, field_attr)| {
f(&field_name, &field_attr)
}).collect()
}
fn create_field_get(field_name: &str, ty: &Field) -> TokenStream2 {
let name: syn::Ident = syn::parse_str(&field_name).expect("名称转换错误");
match ty {
Field::Int | Field::Datetime => quote! {
let #name: i32 = match row.try_get(#field_name) {
Err(_) => 0,
Ok(x) => x,
};
},
Field::String => quote! {
let #name: String = match row.try_get(#field_name) {
Err(_) => String::from(""),
Ok(x) => x,
};
},
Field::Double => quote! {
let #name: f64 = match row.try_get(#field_name) {
Err(_) => 0.0,
Ok(x) => x,
};
},
Field::OneToOne(_, _) | Field::ManyToOne(_, _) => quote! {
let #name = None;
},
Field::OneToMany(_, _) => quote! {
let #name = Vec::new();
},
}
}
fn create_field_test(field_name: &str, ty: &Field) -> TokenStream2 {
let name: syn::Ident = syn::parse_str(&field_name).expect("名称转换错误");
match ty {
Field::Int => quote! { let #name: i32 = value.get(#field_name).expect(&format!("test字段不存在, {}", #field_name)).as_int(); },
Field::String => quote! { let #name: String = value.get(#field_name).expect(&format!("test字段不存在, {}", #field_name)).as_string(); },
Field::Double => quote! {
let #name: f64 = value.get(#field_name).expect(&format!("test字段不存在, {}", #field_name)).as_double();
},
Field::Datetime => quote! {
let #name = value.get(#field_name).expect(&format!("test字段不存在, {}", #field_name)).as_datetime();
},
Field::OneToOne(_, _) | Field::ManyToOne(_, _) => quote! {
let #name = None;
},
Field::OneToMany(_, _) => quote! {
let #name = Vec::new();
},
}
}
fn create_field_clone(field_name: &str, ty: &Field) -> TokenStream2 {
let name: syn::Ident = syn::parse_str(&field_name).expect("名称转换错误");
match ty {
Field::Int | Field::Double | Field::Datetime => quote! { let #name = self.#name; },
Field::String => quote! { let #name = self.#name.to_string(); },
Field::OneToOne(_, _) | Field::ManyToOne(_, _) => quote! {
let #name = None;
},
Field::OneToMany(_, _) => quote! {
let #name = Vec::new();
},
}
}
fn create_record(field_name: &str) -> TokenStream2 {
let name: syn::Ident = syn::parse_str(&field_name).expect(&format!("变量名不合法, {}", field_name));
let field = quote! {#name:#name,};
field
}
fn create_copy(field_name: &str, ty: &Field) -> TokenStream2 {
let name: syn::Ident = syn::parse_str(&field_name).expect(&format!("变量名不合法, {}", field_name));
match ty {
Field::Int | Field::Double | Field::Datetime => quote! { entity.#name = other.#name; },
Field::String => quote! { entity.#name = other.#name.to_string(); },
Field::OneToOne(_, _) | Field::OneToMany(_, _) | Field::ManyToOne(_, _) => quote! {},
}
}