cbinder/src/lib.rs

90 lines
2.9 KiB
Rust

use proc_macro::TokenStream;
use quote::quote;
use syn;
// cbind!(fn start_cwtch(app_dir: &str, tor_path: &str) -> i32 {c_StartCwtch});
#[proc_macro]
pub fn cbind(_def: TokenStream) -> TokenStream {
let ast: syn::ItemFn = syn::parse(_def).unwrap();
let (fn_name, fn_args, fn_ret, fn_call) = extract(ast);
dbg!(generate(fn_name, fn_args, fn_ret, fn_call));
TokenStream::new()
}
fn extract(ast: syn::ItemFn) -> (String, Vec<(String, String)>, Option<String>, String) {
let fn_name = ast.sig.ident.to_string();
let fn_call = match &ast.block.stmts[0] {
syn::Stmt::Expr(expr) => match expr {
syn::Expr::Path(expr) => expr.path.segments[0].ident.to_string(),
_ => panic!("Could not find binding function to call, did you include '{}'", "{ bingden_fn_to_call() }"),
}
_ => panic!("Could not find binding function to call, did you include '{}'", "{ bingden_fn_to_call() }"),
};
let ret_type = match &ast.sig.output {
syn::ReturnType::Type(_, box_type) => {
let ty = &**box_type;
match ty {
syn::Type::Path(p) => {
if p.path.segments.len() == 1 {
Some(p.path.segments[0].ident.to_string())
} else {
None
}
}
_ => None
}
}
_ => None
};
let mut args: Vec<(String, String)> = vec!();
for arg in &ast.sig.inputs {
let arg_name = match arg {
syn::FnArg::Typed(pat_type) => {
(match &*pat_type.pat {
syn::Pat::Ident(ident) => ident.ident.to_string(),
_ => panic!("Could not find argument name")
},
match &*pat_type.ty {
syn::Type::Reference(tref) => match &*tref.elem {
syn::Type::Path(path) => path.path.segments[0].ident.to_string(),
_ => panic!("Could not find argument type")
},
_ => panic!("Could not find argument type")
})
}
_ => panic!("Could not find expected argument")
};
args.push(arg_name);
};
(fn_name, args, ret_type, fn_call)
}
fn generate(fn_name: String, fn_args: Vec<(String, String)>, fn_ret: Option<String>, fn_call: String) -> TokenStream {
let mut arg_str = "&self".to_string();
for arg in fn_args {
arg_str.push_str(format!(", {}: {}", arg.0, arg.1).as_str());
}
dbg!(&arg_str);
dbg!(quote!(fn start_cwtch(&self, arg1: &str, arg2: &str) {} ));
dbg!(quote!("fn start_cwtch(&self, arg1: &str, arg2: &str) {} "));
quote!(fn #fn_name(#arg_str) {}).into()
//TokenStream::new()
}
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
let result = 2 + 2;
assert_eq!(result, 4);
}
}