use crate::route_file::route_cfg;
use hirust_auth;
use proc_macro::{TokenStream, TokenTree};
use serde_json::Value;
use std::collections::HashMap;
use std::fs::{File, OpenOptions};
use std::io;
use std::io::Write;
use std::path::Path;
use zip::ZipArchive;
#[allow(dead_code)]
pub fn create_file(file_path: &str) {
if !Path::new(file_path).exists() {
match std::fs::File::create(file_path) {
Ok(_) => println!("文件创建成功:{}", file_path),
Err(e) => println!("创建文件失败:{}", e),
}
}
}
#[allow(dead_code)]
pub fn create_and_append(file_path: &str, content: &str) {
create_file(file_path);
match OpenOptions::new().append(true).open(file_path) {
Ok(mut file) => {
if let Err(e) = writeln!(file, "{}", content) {
println!("追加内容失败:{}", e);
}
}
Err(e) => println!("打开文件失败:{}", e),
}
}
#[allow(dead_code)]
pub fn write_file(file_path: &str, content: &str) {
match OpenOptions::new().write(true).open(file_path) {
Ok(mut file) => {
if let Err(e) = writeln!(file, "{}", content) {
println!("写文件内容失败:{}", e);
}
}
Err(e) => println!("打开文件失败:{}", e),
}
}
#[allow(dead_code)]
pub fn reverse_string(s: &str) -> String {
s.chars().rev().collect::<String>()
}
#[allow(dead_code)]
pub fn extract_zip(zip_path: &str, extract_to: &str) -> io::Result<()> {
let file = File::open(zip_path)?;
let mut archive = ZipArchive::new(file)?;
for i in 0..archive.len() {
let mut file_in_zip = archive.by_index(i)?;
let outpath = match file_in_zip.enclosed_name() {
Some(path) => {
let mut path_buf = Path::new(extract_to).to_path_buf();
path_buf.push(path);
path_buf
}
None => continue,
};
if file_in_zip.is_dir() {
std::fs::create_dir_all(&outpath)?;
} else {
if let Some(p) = outpath.parent() {
if !p.exists() {
std::fs::create_dir_all(&p)?;
}
}
let mut outfile = File::create(&outpath)?;
io::copy(&mut file_in_zip, &mut outfile)?;
}
}
Ok(())
}
#[allow(unused)]
pub fn parse_token(args: TokenStream, req_map: HashMap<String, String>) -> (String, String) {
let auth_info = parse_attr(args);
let path = auth_info.clone().path.clone();
let tag = auth_info.clone().tag.clone();
let middlewares: Vec<String> = auth_info
.clone()
.middleware
.clone()
.split(",")
.map(|m| m.to_string().replace(" ", ""))
.collect();
match hirust_auth::exist(tag.clone()) {
Some(_) => {
panic!("This handler tag: {} is duplication", tag.clone());
}
None => {
let route_cfg = route_cfg();
if route_cfg.is_empty() {
panic!(
"file: {}, line: {}, message: route config is empty, please check the route configuration path and compilation order.",
file!(),
line!()
);
}
let serialized = serde_json::to_string(&auth_info.clone()).unwrap();
create_and_append(route_cfg.as_str(), &serialized.as_str());
}
}
let mut contents = String::new();
if !middlewares.is_empty() {
let mut req = String::new();
if req_map.contains_key("actix_web::HttpRequest") {
req = "&".to_owned() + &*req_map.get("actix_web::HttpRequest").unwrap().to_string();
} else if req_map.contains_key("HttpRequest") {
req = "&".to_owned() + &*req_map.get("HttpRequest").unwrap().to_string();
} else if req_map.contains_key("&HttpRequest") {
req = req_map.get("&HttpRequest").unwrap().to_string();
} else {
panic!(
"There is no request parameter {} `actix_web::HttpRequest`",
req
);
}
for middleware in middlewares {
let temp = format!(
r#"
match interceptor({}({}, {})) {{
Some(response) => return response.respond_to({}),
_ => (),
}}
"#,
middleware,
req.clone().to_string(),
tag.clone().to_string(),
req.clone().to_string()
);
contents += &temp;
}
contents = format!(r#"{{{}}}"#, contents);
} else {
contents = format!(r#"{{{}}}"#, "");
}
(path, contents)
}
#[allow(unused)]
pub fn parse_attr(args: TokenStream) -> hirust_auth::Auth {
let mut is_method = false;
let mut method = String::new();
let mut is_path = false;
let mut path = String::new();
let mut is_middleware = false;
let mut middlewares: Vec<String> = vec![];
let mut middleware = String::new();
let mut is_tag = false;
let mut tag = String::new();
let mut is_auth = false;
let mut auth = true;
let mut is_desc = false;
let mut desc = String::new();
for arg in args.into_iter() {
if matches!(&arg, TokenTree::Ident(_)) && "method".eq(&arg.to_string()) {
is_method = true;
}
if is_path && matches!(&arg, TokenTree::Literal(_)) {
let temp = arg.to_string();
method = temp.clone().replace("\"", "");
is_method = false;
}
if matches!(&arg, TokenTree::Ident(_)) && "path".eq(&arg.to_string()) {
is_path = true;
}
if is_path && matches!(&arg, TokenTree::Literal(_)) {
let temp = arg.to_string();
path = temp.clone().replace("\"", "");
is_path = false;
}
if matches!(&arg, TokenTree::Ident(_)) && "middleware".eq(&arg.to_string()) {
is_middleware = true;
}
if is_middleware && matches!(&arg, TokenTree::Group(_)) {
middleware = arg.to_string();
middleware = middleware
.clone()
.replace("{", "")
.replace("}", "")
.replace(" ", "");
middlewares = middleware
.split(",")
.map(|m| m.to_string().replace(" ", ""))
.collect();
is_middleware = false;
}
if matches!(&arg, TokenTree::Ident(_)) && "tag".eq(&arg.to_string()) {
is_tag = true;
}
if is_tag && matches!(&arg, TokenTree::Literal(_)) {
tag = arg.clone().to_string();
is_tag = false
}
if matches!(&arg, TokenTree::Ident(_)) && "auth".eq(&arg.to_string()) {
is_auth = true;
}
if is_auth && !"auth".eq(&arg.to_string()) && matches!(&arg, TokenTree::Ident(_)) {
if "false".eq(&arg.to_string()) {
auth = false;
}
is_auth = false;
}
if matches!(&arg, TokenTree::Ident(_)) && "desc".eq(&arg.to_string()) {
is_desc = true;
}
if is_desc && matches!(&arg, TokenTree::Literal(_)) {
let temp = arg.to_string(); desc = temp.replace("\"", "");
is_desc = false;
}
}
hirust_auth::Auth {
method: method.clone().replace("\"", ""),
path: path.clone().replace("\"", ""),
tag: tag.clone().replace("\"", ""),
desc: desc.clone().replace("\"", ""),
middleware: middleware.clone().replace("\"", ""),
auth: auth.to_string(),
}
.clone()
}
#[allow(unused)]
pub fn parse_auth_info(args: proc_macro2::TokenStream) -> hirust_auth::Auth {
let mut method = String::new();
let serialized = serde_json::to_string(&hirust_auth::Auth::default())
.expect("struct Auth serialization failed");
let json_value: Value = serde_json::from_str(&serialized).expect("JSON was not well-formatted");
let auth_keys_map: HashMap<String, Value> =
serde_json::from_value(json_value).expect("JSON was not well-formatted");
let mut keys: Vec<String> = vec![];
let mut values: Vec<String> = vec![];
for arg in args.clone().into_iter() {
match arg {
proc_macro2::TokenTree::Group(ref group) => {
let group_tokens = group.stream();
for inner_group in group_tokens {
match inner_group {
proc_macro2::TokenTree::Ident(ref ident) => {
method = ident.clone().to_string().replace("\"", "");
}
proc_macro2::TokenTree::Group(ref group) => {
let group_tokens = group.stream();
for inner_group in group_tokens {
match inner_group {
proc_macro2::TokenTree::Ident(ref ident) => {
if auth_keys_map.contains_key(&ident.to_string()) {
keys.push(ident.to_string());
} else {
values.push(ident.to_string().replace("\"", ""));
}
}
proc_macro2::TokenTree::Literal(ref literal) => {
values.push(literal.to_string().replace("\"", ""));
}
proc_macro2::TokenTree::Group(ref group) => {
let group_tokens = group.stream();
values.push(
group_tokens.to_string().replace(" ", "").to_string(),
);
}
_ => {}
}
}
}
_ => {}
}
}
}
_ => {}
}
}
let mut attr_map: HashMap<String, String> = HashMap::new();
attr_map.insert("method".to_string(), method.to_string());
for index in 0..keys.len() {
attr_map.insert(keys[index].to_string(), values[index].to_string());
}
let mut auth_map: HashMap<String, String> = HashMap::new();
for (key, value) in auth_keys_map {
if attr_map.contains_key(key.as_str()) {
auth_map.insert(key.clone(), attr_map.get(&key).unwrap().to_string());
} else {
if key.clone().eq("auth") {
auth_map.insert(key.clone(), "true".to_string());
} else {
auth_map.insert(key.clone(), String::new());
}
}
}
if auth_map.get("path").unwrap().is_empty() {
panic!("path cannot be empty.");
}
if auth_map.get("tag").unwrap().is_empty() {
}
let serialized = serde_json::to_string(&auth_map).expect("attr_map serialization failed");
let auth_info: hirust_auth::Auth =
serde_json::from_str(&serialized).expect("JSON was not well-formatted");
auth_info.clone()
}
#[allow(unused)]
pub fn parse_group_extract_args(tokens: proc_macro2::TokenStream) -> HashMap<String, String> {
let mut args_map = HashMap::<String, String>::new();
for token in tokens.into_iter() {
match token {
proc_macro2::TokenTree::Group(ref group) => {
let mut key = String::new();
let mut value = String::new();
let mut punctuation = String::new();
let mut punctuation_counter = 0;
let inner_tokens = group.stream();
for inner_tt in inner_tokens {
match inner_tt {
proc_macro2::TokenTree::Ident(ref ident) => {
if punctuation.is_empty() {
value = ident.clone().to_string();
} else {
if punctuation_counter >= 1 {
key = key + &*ident.clone().to_string();
}
}
}
proc_macro2::TokenTree::Punct(ref punct) => {
if punct.to_string() == ":" {
punctuation_counter += 1;
punctuation = punct.clone().to_string();
if punctuation_counter > 1 {
key = key + &*punct.clone().to_string();
}
} else if punct.to_string() == "," {
args_map.insert(key.clone(), value.clone());
key = String::new();
value = String::new();
punctuation = String::new();
punctuation_counter = 0;
} else {
key = key + &*punct.clone().to_string();
}
}
_ => (), }
}
if !key.is_empty() && !value.is_empty() {
args_map.insert(key.clone(), value.clone());
}
}
_ => (), }
}
args_map
}
#[allow(unused)]
pub fn parse_group_extract_scope(tokens: proc_macro2::TokenStream) -> HashMap<String, String> {
let mut args_map = HashMap::<String, String>::new();
for token in tokens.into_iter() {
match token {
proc_macro2::TokenTree::Group(ref group) => {
let mut key = String::new();
let mut value = String::new();
let mut punctuation = String::new();
let mut punctuation_counter = 0;
let inner_tokens = group.stream();
for inner_tt in inner_tokens {
match inner_tt {
proc_macro2::TokenTree::Ident(ref ident) => {
if punctuation.is_empty() {
value = ident.clone().to_string();
} else {
if punctuation_counter >= 1 {
key = key + &*ident.clone().to_string();
}
}
}
proc_macro2::TokenTree::Punct(ref punct) => {
if punct.to_string() == ":" {
punctuation_counter += 1;
punctuation = punct.clone().to_string();
if punctuation_counter > 1 {
key = key + &*punct.clone().to_string();
}
} else if punct.to_string() == "," {
args_map.insert(key.clone(), value.clone());
key = String::new();
value = String::new();
punctuation = String::new();
punctuation_counter = 0;
} else {
key = key + &*punct.clone().to_string();
}
}
_ => (), }
}
if !key.is_empty() && !value.is_empty() {
args_map.insert(key.clone(), value.clone());
}
}
_ => (), }
}
args_map
}