use proc_macro::TokenStream;
use quote::{quote, ToTokens};
use std::{fs, env};
use std::io::Read;
use std::path;
use std::path::PathBuf;
use substring::Substring;
use syn::ext::IdentExt;
use syn::{parse_macro_input, token::Token, Attribute, DeriveInput, Ident, Item, ItemFn, Stmt};
#[allow(warnings)]
pub fn impl_extends_struct(_attr: TokenStream, _input: TokenStream) -> TokenStream {
let mut derive = String::new();
let mut extends = String::new();
let attr_str = _attr
.to_string()
.replace("/", "")
.replace('\n', "")
.replace('\\', "")
.replace('"', "")
.replace(" ", "");
let attr_split = attr_str.split("&&");
attr_split.for_each(|_atrra| {
let (key, val) = _atrra.split_once("=").unwrap();
if let "derive" = key {
derive = val.to_string();
}
if let "extends" = key {
extends = val.to_string();
}
});
let (content_code_str, derive_vec) = split_mod_str(extends);
if (derive.len() > 0) {
derive += ",";
}
for der in derive_vec {
if (!derive.contains(&der)) {
derive += &der;
derive += ",";
}
}
derive = derive.split_at(derive.rfind(",").unwrap()).0.to_string();
let derive_input = parse_macro_input!(_input as DeriveInput);
let struct_name = derive_input.ident;
let struct_name_str = struct_name.to_string();
let mut attr_ald = vec![];
let mut attr_str_vec: Vec<String> = vec![];
match &derive_input.data {
syn::Data::Struct(ds) => match &ds.fields {
syn::Fields::Named(ff) => {
ff.named.iter().for_each(|f| {
let identtrri = &f.ident;
let ty = &f.ty;
let afs = quote! {pub #identtrri:#ty,};
attr_ald.push(afs);
});
}
_ => (),
},
_ => (),
}
let extents_parent_attr = content_code_str
.parse::<proc_macro2::TokenStream>()
.unwrap();
let mut extents_parent_derive = String::new();
if (derive.len() > 0) {
extents_parent_derive = "#[derive(".to_string() + &derive + ")]";
}
let derive_code = extents_parent_derive
.parse::<proc_macro2::TokenStream>()
.unwrap();
let clone_struct_quote = quote! {
#derive_code
struct #struct_name {
#(#attr_ald)*
#extents_parent_attr
}
};
let clone_struct_new_model_quote = quote! {
#struct_name {
#(#attr_ald)*
#extents_parent_attr
}
};
let struct_all_code_str = clone_struct_new_model_quote.to_string();
let right_st_str = &struct_all_code_str
.split_at(struct_all_code_str.find("{").unwrap() + 1)
.1;
let center_code_str = right_st_str.split_at(right_st_str.find("}").unwrap()).0;
let attr_code_str_split = center_code_str.trim().split(",");
let mut new_none_str = String::new();
attr_code_str_split.for_each(|f| {
if (f.contains(":")) {
let (attr_name, _) = f.split_once(":").unwrap();
new_none_str += &(attr_name.replace("pub", "").to_string() + ":None,");
}
});
let new_none_ts = new_none_str.parse::<proc_macro2::TokenStream>().unwrap();
let clone_struct_new_none_fn_quote = quote! {
pub fn new_none()->#struct_name{
#struct_name {
#new_none_ts
}
}
};
let clone_struct_stream = TokenStream::from(clone_struct_quote);
let clone_struct = parse_macro_input!(clone_struct_stream as DeriveInput);
match &clone_struct.data {
syn::Data::Struct(ds) => match &ds.fields {
syn::Fields::Named(ff) => {
ff.named.iter().for_each(|f| {
let identtrri = &f.ident;
let ty = &f.ty;
let mut attr_name_str = String::from("");
let mut ty_str = String::new();
match identtrri {
Some(r) => {
attr_name_str = r.to_string();
}
_ => {}
}
match ty {
syn::Type::Path(p) => {
let attr_str = p.path.segments.to_token_stream().to_string();
if (attr_str.contains("Option")) {
ty_str = attr_str
.to_string()
.substring(
attr_str.find("<").unwrap() + 1,
attr_str.rfind(">").unwrap(),
)
.trim()
.to_string();
} else {
ty_str = attr_str.trim().to_string();
}
}
_ => {}
}
let attr_str = attr_name_str + ":" + &ty_str;
attr_str_vec.push(attr_str);
});
}
_ => (),
},
_ => (),
}
let attr_impl = quote! {
impl #struct_name{
pub fn get_struct_name()->String{
String::from(#struct_name_str)
}
pub fn get_struct_attr_str()->Vec<String>{
vec!(#(String::from(#attr_str_vec)),*)
}
#clone_struct_new_none_fn_quote
}
};
let apai = TokenStream::from(quote! {
#clone_struct
#attr_impl
});
eprintln!("steam:{:#?}", apai.to_string());
apai.into()
}
#[allow(warnings)]
fn split_mod_str(extends: String) -> (std::string::String, std::vec::Vec<String>) {
let mut extends_path = String::new();
let extends_split = extends.split("::");
let mut config_path = String::new();
let config_path_rs = env::current_dir();
if let Ok(r)=config_path_rs{
if let Some(s) = r.to_str(){
config_path = s.to_string();
}
}
println!("config_path:{:?}",config_path);
extends_path += &config_path;
let mut split_vec = vec![];
extends_split.for_each(|f| {
split_vec.push(f);
});
if !extends.starts_with("crate") {
let mut salsh_idx = extends_path.rfind("\\");
if salsh_idx == None {
salsh_idx = extends_path.rfind("/");
}
let (f_str, _) = extends_path.split_at(salsh_idx.unwrap());
extends_path = f_str.to_string() + "/";
if (!path::Path::new(format!("{}{}", extends_path, split_vec[0]).as_str()).exists()) {
extends_path = extends_path
.split_at(extends_path.rfind("\\").unwrap())
.0
.to_string()
+ "/";
}
extends_path += split_vec[0];
}
extends_path += "/src";
let mut mod_name = String::new();
let split_size = split_vec.len();
if split_size < 1 {
panic!("error");
} else if split_vec.len() == 2 {
extends_path += "/";
mod_name = split_vec[1].to_string();
let path_check_url_lib = extends_path.clone() + "/lib.rs";
let paht_exist = path::Path::new(&path_check_url_lib);
if (paht_exist.exists()) {
extends_path = path_check_url_lib;
} else {
extends_path = extends_path.clone() + "/main.rs";
}
} else {
let mut idx = 0_usize;
for f in split_vec {
idx += 1;
if idx < 2 {
continue;
}
if (idx >= split_size) {
extends_path += ".rs";
mod_name = f.to_string();
break;
}
extends_path += "/";
extends_path += f;
}
}
let (block_name, type_name) = mod_name.split_once("@").unwrap();
let file_path = path::Path::new(&extends_path);
let mut file_rs = fs::File::open(file_path);
let mut read_str = String::new();
if let Ok(mut r)=file_rs{
r.read_to_string(&mut read_str);
}
let mut codesln = vec![];
let rsp = read_str.split("\n");
let mut row_idx = 0_usize;
let mut first_row = 0_usize;
let mut start_read = false;
let mut ln_idx = vec![];
rsp.for_each(|f| {
codesln.push(f);
if f.contains("struct") && f.contains(&block_name) && f.contains("{") {
first_row = row_idx;
start_read = true;
}
if (start_read) {
ln_idx.push(row_idx);
if f.contains("}") {
start_read = false;
}
}
row_idx += 1;
});
let mut dervie_vec = vec![];
if(first_row<1){
panic!("error")
}
let derive_dome_str = codesln[first_row - 1];
if (derive_dome_str.contains("#[derive(")) {
let str_s1 = derive_dome_str
.split_at(derive_dome_str.find("(").unwrap() + 1)
.1;
let str_rs = str_s1.split_at(str_s1.find(")").unwrap()).0;
str_rs.split(",").for_each(|f| {
dervie_vec.push(f.trim().to_string());
});
}
let mut content_code_str = String::new();
let mut content_idx = 0_usize;
let blook_code_len = ln_idx.len();
if(blook_code_len>0){
for number in ln_idx {
if (content_idx >= 1 && content_idx < (blook_code_len - 1)) {
content_code_str += codesln[number];
}
content_idx += 1;
}
}
println!(
"content_code_str:{:?},d-vec:{:?}",
content_code_str, dervie_vec
);
(content_code_str, dervie_vec)
}