diff --git a/dart-warp b/dart-warp index d241451..b6e49a5 160000 --- a/dart-warp +++ b/dart-warp @@ -1 +1 @@ -Subproject commit d24145165aafcffd7938b83a888b22eafa8d0318 +Subproject commit b6e49a51886c3956b90fb9d444c7c2cc8e599127 diff --git a/warp-macros/src/lib.rs b/warp-macros/src/lib.rs index 5919ea0..57c8ff7 100644 --- a/warp-macros/src/lib.rs +++ b/warp-macros/src/lib.rs @@ -4,18 +4,16 @@ use proc_macro2::Span; use proc_macro_error::{abort, proc_macro_error}; use quote::quote; use syn::{ - parse_macro_input, parse_quote, punctuated::Punctuated, FnArg, GenericArgument, Ident, ItemFn, - Meta, Pat, PathArguments, ReturnType, Signature, Type, + parse_macro_input, parse_quote, FnArg, GenericArgument, Ident, ItemFn, + Pat, PathArguments, ReturnType, Signature, Type, }; #[proc_macro_attribute] #[proc_macro_error] -pub fn c_export(attr: TokenStream, item: TokenStream) -> TokenStream { - let attr = parse_macro_input!(attr with Punctuated::parse_terminated); - let asyn = Ident::new("asyn", Span::call_site()); - let is_async = attr.iter().any(|a| a.path().get_ident() == Some(&asyn)); +pub fn c_export(_attr: TokenStream, item: TokenStream) -> TokenStream { let input = parse_macro_input!(item as ItemFn); let sig = &input.sig; + let is_async = sig.asyncness.is_some(); let vec_reg = regex::Regex::new(r"Vec < (\w+) >").unwrap(); let Signature { @@ -51,9 +49,14 @@ pub fn c_export(attr: TokenStream, item: TokenStream) -> TokenStream { map_result(res) } } - "String" => quote! { - map_result_string(res) - }, + "String" => { + c_result_type = parse_quote! { + *mut c_char + }; + quote! { + map_result_string(res) + } + } "Vec < u8 >" => { c_result_type = parse_quote! { *const u8 @@ -113,14 +116,17 @@ pub fn c_export(attr: TokenStream, item: TokenStream) -> TokenStream { let ItemFn { vis, block, .. } = &input; let mut wrapped_fnargs = vec![]; - let mut str_convs = vec![]; - let mut bytes_convs = vec![]; + let mut convs = vec![]; let mut has_network = false; let mut has_connection = false; + let mut mut_connection = false; let mut has_client = false; for input in inputs.iter() { if let FnArg::Typed(pat) = input { if let Pat::Ident(param) = pat.pat.as_ref() { + let p = pat.ty.as_ref(); + let type_name = quote! { #p }.to_string(); + let ident = ¶m.ident; let name = ident.to_string(); match name.as_str() { @@ -130,6 +136,9 @@ pub fn c_export(attr: TokenStream, item: TokenStream) -> TokenStream { } "connection" => { has_connection = true; + if type_name == "& mut Connection" { + mut_connection = true; + } continue; } "client" if is_async => { @@ -138,11 +147,9 @@ pub fn c_export(attr: TokenStream, item: TokenStream) -> TokenStream { } _ => {} } - let p = pat.ty.as_ref(); - let s = quote! { #p }.to_string(); - match s.as_str() { + match type_name.as_str() { "& str" => { - str_convs.push(quote! { + convs.push(quote! { let #ident = unsafe { CStr::from_ptr(#ident).to_string_lossy() }; let #ident = &#ident; }); @@ -153,23 +160,47 @@ pub fn c_export(attr: TokenStream, item: TokenStream) -> TokenStream { continue; } "& [u8]" => { - bytes_convs.push(quote! { + convs.push(quote! { let #ident = unsafe { - let ptr_len = #ident as *mut u32; - let len = *ptr_len as usize; - let ptr_data = value.offset(4); - Vec::::from_raw_parts(ptr_data, len, len) + let ptr_data = #ident.value; + let len = #ident.len as usize; + let data = Vec::::from_raw_parts(ptr_data, len, len); + data }; let #ident = &#ident[..]; }); let input: FnArg = parse_quote! { - #ident: *mut u8 + #ident: CParam }; wrapped_fnargs.push(input); continue; } - _ => { + _ if type_name.ends_with("T") => { + let tpe = Ident::new( + type_name + .strip_suffix("T") + .unwrap() + .strip_prefix("& ") + .unwrap(), + Span::call_site(), + ); + convs.push(quote! { + let #ident = unsafe { + let ptr_data = #ident.value; + let len = #ident.len as usize; + let data = Vec::::from_raw_parts(ptr_data, len, len); + let object = flatbuffers::root::<#tpe>(&data).unwrap(); + object.unpack() + }; + let #ident = &#ident; + }); + let input: FnArg = parse_quote! { + #ident: CParam + }; + wrapped_fnargs.push(input); + continue; } + _ => {} } } } @@ -178,14 +209,21 @@ pub fn c_export(attr: TokenStream, item: TokenStream) -> TokenStream { let network = if has_network { quote! { - let network = &coin.network; + let network = &coin.network.clone(); } } else { quote! {} }; let connection = if has_connection { - quote! { - let connection = &coin.connection()?; + if mut_connection { + quote! { + let mut connection = coin.connection()?; + let connection: &mut rusqlite::Connection = &mut connection; + } + } else { + quote! { + let connection = &coin.connection()?; + } } } else { quote! {} @@ -220,12 +258,14 @@ pub fn c_export(attr: TokenStream, item: TokenStream) -> TokenStream { #[tokio::main] pub async extern "C" fn #wrapper(coin: u8, #(#wrapped_fnargs),*) -> CResult<#c_result_type> { let res = async { - let coin = COINS[coin as usize].lock(); + let coin = { + let c = COINS[coin as usize].lock(); + c.clone() + }; #network #connection #client - #(#str_convs),* - #(#bytes_convs),* + #(#convs)* #ident(#(#args),*).await }; let res = res.await; @@ -239,12 +279,14 @@ pub fn c_export(attr: TokenStream, item: TokenStream) -> TokenStream { #[no_mangle] pub extern "C" fn #wrapper(coin: u8, #(#wrapped_fnargs),*) -> CResult<#c_result_type> { let res = || { - let coin = COINS[coin as usize].lock(); + let coin = { + let c = COINS[coin as usize].lock(); + c.clone() + }; #network #connection #client - #(#str_convs),* - #(#bytes_convs),* + #(#convs)* #ident(#(#args),*) }; let res = res(); diff --git a/zcash-warp b/zcash-warp index 7fb49f6..87396f5 160000 --- a/zcash-warp +++ b/zcash-warp @@ -1 +1 @@ -Subproject commit 7fb49f618e6f1849bc2e66de908d97ac7d03ae50 +Subproject commit 87396f5558ed984387150e566bd4e9c3f9e4f6d4