use crate::table_dao::model::table;
use std::collections::HashMap;
use std::{env, fs};
use std::path::Path;
use std::sync::{LazyLock, Mutex};
const MOD_COMMON_SRC: &'static str = r##"
pub struct PageIn {
/// 当前页
pub(crate) page: u32,
/// 页面显示件数
pub(crate) page_size: u32,
/// 排序字段
pub(crate) sort_key: String,
/// 排序方式
pub(crate) sort_type: String,
}
impl PageIn {
/// 验证排序是否合法
pub fn check_order_by(&self) -> Result<(), sqlx::Error> {
for ch in self.sort_key.chars() {
if !(ch.is_ascii_alphanumeric() || ch == '_' || ch == '.' || ch == ',' || ch == ' ') {
return Err(sqlx::Error::InvalidArgument("排序方式中存在非法字符".to_string()));
}
}
match self.sort_type.to_lowercase().as_str() {
"asc" | "desc" | "" => {}
_ => {
return Err(sqlx::Error::InvalidArgument("排序方式中存在非法字符".to_string()));
}
}
Ok(())
}
}
"##;
static METHOD_DAO_SOURCE_PREPARE: LazyLock<Mutex<HashMap<String, MethodSource>>> =
LazyLock::new(|| Mutex::new(HashMap::new()));
static METHOD_DAO_ENTITY_PREPARE: LazyLock<Mutex<HashMap<String, HashMap<String, table::Entity>>>> =
LazyLock::new(|| Mutex::new(HashMap::new()));
pub fn add_method_source(mod_name: &str, src: String) {
let mut source_map = METHOD_DAO_SOURCE_PREPARE.lock().unwrap();
if source_map.contains_key(mod_name) {
source_map
.get_mut(mod_name)
.unwrap()
.src
.push_str(src.as_str());
} else {
source_map.insert(
mod_name.to_string(),
MethodSource {
mod_name: mod_name.to_string(),
src,
},
);
}
}
pub fn add_entity(mod_name: &str, table: table::Entity) {
let mut entity_map = METHOD_DAO_ENTITY_PREPARE.lock().unwrap();
if !entity_map.contains_key(mod_name) {
entity_map.insert(mod_name.to_string(), HashMap::new());
}
let map = entity_map.get_mut(mod_name).unwrap();
let entity_name = table.entity_name();
if !map.contains_key(entity_name.as_str()) {
map.insert(entity_name, table);
}
}
pub fn write() {
let source_map = METHOD_DAO_SOURCE_PREPARE.lock().unwrap();
let entity_file_map = METHOD_DAO_ENTITY_PREPARE.lock().unwrap();
let mut all_source = format!("// Generated at {}\n", chrono::Local::now().to_rfc3339());
all_source.push_str(MOD_COMMON_SRC);
source_map.iter().for_each(|(mod_name, method)| {
let mut source = method.src.clone();
if let Some(entity_map) = entity_file_map.get(mod_name) {
entity_map.iter().for_each(|(_, table)| {
source.push_str(table.make_entity_struct().as_str());
});
}
all_source.push_str(format!("pub mod {}_dao {{\n{}\n}}\n", mod_name, source).as_str());
});
format_and_write(&all_source);
}
fn format_and_write(source: &str) {
let save_file = Path::new(&(env::var("OUT_DIR").unwrap().as_str())).join("dao.rs");
let rust_src = syn::parse_str(source);
match rust_src {
Err(err) => {
eprintln!("cargo:warning=解析代码文件出错:{:?}", err);
fs::write(&save_file, source).unwrap();
}
Ok(it) => {
let formatted_rust_src = prettyplease::unparse(&it);
fs::write(&save_file, formatted_rust_src).unwrap();
}
}
println!(
"cargo:warning=Generated DAO source saved to '{}'",
save_file.display()
);
}
struct MethodSource {
mod_name: String,
src: String,
}