X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=c-bindings-gen%2Fsrc%2Fmain.rs;h=0e9a42286a1434ef6a8e3ea4f8c60356277c658e;hb=077c4d770eaa919ed9f4aef56375abe9ef50e55a;hp=975db567dcbc35cb560c88cd6f433b288e69b0de;hpb=50af954e76be66d0a1a4e3ba210bd849c4780b8d;p=ldk-c-bindings diff --git a/c-bindings-gen/src/main.rs b/c-bindings-gen/src/main.rs index 975db56..0e9a422 100644 --- a/c-bindings-gen/src/main.rs +++ b/c-bindings-gen/src/main.rs @@ -18,7 +18,7 @@ //! It also generates relevant memory-management functions and free-standing functions with //! parameters mapped. -use std::collections::{HashMap, hash_map}; +use std::collections::{HashMap, hash_map, HashSet}; use std::env; use std::fs::File; use std::io::{Read, Write}; @@ -271,7 +271,7 @@ macro_rules! get_module_type_resolver { let mut module_iter = module.rsplitn(2, "::"); module_iter.next().unwrap(); let module = module_iter.next().unwrap(); - let imports = ImportResolver::new(module.splitn(2, "::").next().unwrap(), &$crate_types.lib_ast.dependencies, + let imports = ImportResolver::new(module.splitn(2, "::").next().unwrap(), &$crate_types.lib_ast, module, &$crate_types.lib_ast.modules.get(module).unwrap().items); TypeResolver::new(module, imports, $crate_types) } } @@ -677,7 +677,7 @@ fn writeln_opaque(w: &mut W, ident: &syn::Ident, struct_name: writeln!(w, "#[allow(unused)]").unwrap(); writeln!(w, "/// Used only if an object of this type is returned as a trait impl by a method").unwrap(); writeln!(w, "pub(crate) extern \"C\" fn {}_free_void(this_ptr: *mut c_void) {{", struct_name).unwrap(); - writeln!(w, "\tunsafe {{ let _ = Box::from_raw(this_ptr as *mut native{}); }}\n}}", struct_name).unwrap(); + writeln!(w, "\tlet _ = unsafe {{ Box::from_raw(this_ptr as *mut native{}) }};\n}}", struct_name).unwrap(); writeln!(w, "#[allow(unused)]").unwrap(); writeln!(w, "impl {} {{", struct_name).unwrap(); writeln!(w, "\tpub(crate) fn get_native_ref(&self) -> &'static native{} {{", struct_name).unwrap(); @@ -875,7 +875,7 @@ fn writeln_struct<'a, 'b, W: std::io::Write>(w: &mut W, s: &'a syn::ItemStruct, /// Trait struct containing a pointer to the passed struct's inner field and the wrapper functions. /// /// A few non-crate Traits are hard-coded including Default. -fn writeln_impl(w: &mut W, i: &syn::ItemImpl, types: &mut TypeResolver) { +fn writeln_impl(w: &mut W, w_uses: &mut HashSet, i: &syn::ItemImpl, types: &mut TypeResolver) { match export_status(&i.attrs) { ExportStatus::Export => {}, ExportStatus::NoExport|ExportStatus::TestOnly => return, @@ -979,11 +979,11 @@ fn writeln_impl(w: &mut W, i: &syn::ItemImpl, types: &mut Typ // type-conversion logic without actually knowing the concrete native type. if !resolved_path.starts_with(types.module_path) { if !first_seg_is_stdlib(resolved_path.split("::").next().unwrap()) { - writeln!(w, "use crate::{}::native{} as native{};", resolved_path.rsplitn(2, "::").skip(1).next().unwrap(), ident, ident).unwrap(); - writeln!(w, "use crate::{};", resolved_path).unwrap(); - writeln!(w, "use crate::{}_free_void;", resolved_path).unwrap(); + w_uses.insert(format!("use crate::{}::native{} as native{};", resolved_path.rsplitn(2, "::").skip(1).next().unwrap(), ident, ident)); + w_uses.insert(format!("use crate::{};", resolved_path)); + w_uses.insert(format!("use crate::{}_free_void;", resolved_path)); } else { - writeln!(w, "use {} as native{};", resolved_path, ident).unwrap(); + w_uses.insert(format!("use {} as native{};", resolved_path, ident)); } } writeln!(w, "impl From for crate::{} {{", ident, full_trait_path).unwrap(); @@ -1407,7 +1407,7 @@ fn writeln_impl(w: &mut W, i: &syn::ItemImpl, types: &mut Typ } } } else if let Some(resolved_path) = types.maybe_resolve_ident(&ident) { - create_alias_for_impl(resolved_path, i, types, move |aliased_impl, types| writeln_impl(w, &aliased_impl, types)); + create_alias_for_impl(resolved_path, i, types, move |aliased_impl, types| writeln_impl(w, w_uses, &aliased_impl, types)); } else { eprintln!("Not implementing anything for {} due to no-resolve (probably the type isn't pub)", ident); } @@ -1430,7 +1430,7 @@ fn create_alias_for_impl(resolved_pa let alias_resolver_override; let alias_resolver = if alias_module != types.module_path { - alias_resolver_override = ImportResolver::new(types.types.crate_name, &types.crate_types.lib_ast.dependencies, + alias_resolver_override = ImportResolver::new(types.types.crate_name, &types.crate_types.lib_ast, alias_module, &types.crate_types.lib_ast.modules.get(alias_module).unwrap().items); &alias_resolver_override } else { &types.types }; @@ -1779,7 +1779,7 @@ fn writeln_enum<'a, 'b, W: std::io::Write>(w: &mut W, e: &'a syn::ItemEnum, type }; if $ref || new_var { if $ref { - write!(w, "let mut {}_nonref = (*{}).clone();\n\t\t\t\t", $field_ident, $field_ident).unwrap(); + write!(w, "let mut {}_nonref = Clone::clone({});\n\t\t\t\t", $field_ident, $field_ident).unwrap(); if new_var { let nonref_ident = format_ident!("{}_nonref", $field_ident); if $to_c { @@ -1915,7 +1915,7 @@ fn writeln_fn<'a, 'b, W: std::io::Write>(w: &mut W, f: &'a syn::ItemFn, types: & // *** File/Crate Walking Logic *** // ******************************** -fn convert_priv_mod<'a, 'b: 'a, W: std::io::Write>(w: &mut W, libast: &'b FullLibraryAST, crate_types: &CrateTypes<'b>, out_dir: &str, mod_path: &str, module: &'b syn::ItemMod) { +fn convert_priv_mod<'a, 'b: 'a, W: std::io::Write>(w: &mut W, w_uses: &mut HashSet, libast: &'b FullLibraryAST, crate_types: &CrateTypes<'b>, out_dir: &str, mod_path: &str, module: &'b syn::ItemMod) { // We want to ignore all items declared in this module (as they are not pub), but we still need // to give the ImportResolver any use statements, so we copy them here. let mut use_items = Vec::new(); @@ -1924,15 +1924,15 @@ fn convert_priv_mod<'a, 'b: 'a, W: std::io::Write>(w: &mut W, libast: &'b FullLi use_items.push(item); } } - let import_resolver = ImportResolver::from_borrowed_items(mod_path.splitn(2, "::").next().unwrap(), &libast.dependencies, mod_path, &use_items); + let import_resolver = ImportResolver::from_borrowed_items(mod_path.splitn(2, "::").next().unwrap(), libast, mod_path, &use_items); let mut types = TypeResolver::new(mod_path, import_resolver, crate_types); writeln!(w, "mod {} {{\n{}", module.ident, DEFAULT_IMPORTS).unwrap(); for item in module.content.as_ref().unwrap().1.iter() { match item { - syn::Item::Mod(m) => convert_priv_mod(w, libast, crate_types, out_dir, &format!("{}::{}", mod_path, module.ident), m), + syn::Item::Mod(m) => convert_priv_mod(w, w_uses, libast, crate_types, out_dir, &format!("{}::{}", mod_path, module.ident), m), syn::Item::Impl(i) => { - writeln_impl(w, i, &mut types); + writeln_impl(w, w_uses, i, &mut types); }, _ => {}, } @@ -1959,6 +1959,7 @@ fn convert_file<'a, 'b>(libast: &'a FullLibraryAST, crate_types: &CrateTypes<'a> let _ = std::fs::create_dir((&new_file_path.as_ref() as &std::path::Path).parent().unwrap()); let mut out = std::fs::OpenOptions::new().write(true).create(true).truncate(true) .open(new_file_path).expect("Unable to open new src file"); + let mut out_uses = HashSet::default(); writeln!(out, "// This file is Copyright its original authors, visible in version control").unwrap(); writeln!(out, "// history and in the source files from which this was generated.").unwrap(); @@ -2005,7 +2006,7 @@ fn convert_file<'a, 'b>(libast: &'a FullLibraryAST, crate_types: &CrateTypes<'a> eprintln!("Converting {} entries...", module); - let import_resolver = ImportResolver::new(orig_crate, &libast.dependencies, module, items); + let import_resolver = ImportResolver::new(orig_crate, libast, module, items); let mut type_resolver = TypeResolver::new(module, import_resolver, crate_types); for item in items.iter() { @@ -2018,7 +2019,7 @@ fn convert_file<'a, 'b>(libast: &'a FullLibraryAST, crate_types: &CrateTypes<'a> } }, syn::Item::Impl(i) => { - writeln_impl(&mut out, &i, &mut type_resolver); + writeln_impl(&mut out, &mut out_uses, &i, &mut type_resolver); }, syn::Item::Struct(s) => { if let syn::Visibility::Public(_) = s.vis { @@ -2031,7 +2032,7 @@ fn convert_file<'a, 'b>(libast: &'a FullLibraryAST, crate_types: &CrateTypes<'a> } }, syn::Item::Mod(m) => { - convert_priv_mod(&mut out, libast, crate_types, out_dir, &format!("{}::{}", module, m.ident), m); + convert_priv_mod(&mut out, &mut out_uses, libast, crate_types, out_dir, &format!("{}::{}", module, m.ident), m); }, syn::Item::Const(c) => { // Re-export any primitive-type constants. @@ -2101,6 +2102,10 @@ fn convert_file<'a, 'b>(libast: &'a FullLibraryAST, crate_types: &CrateTypes<'a> } } + for use_stmt in out_uses { + writeln!(out, "{}", use_stmt).unwrap(); + } + out.flush().unwrap(); } } @@ -2113,7 +2118,7 @@ fn walk_ast_second_pass<'a>(ast_storage: &'a FullLibraryAST, crate_types: &Crate let ASTModule { ref attrs, ref items, .. } = astmod; assert_eq!(export_status(&attrs), ExportStatus::Export); - let import_resolver = ImportResolver::new(orig_crate, &ast_storage.dependencies, module, items); + let import_resolver = ImportResolver::new(orig_crate, ast_storage, module, items); let mut types = TypeResolver::new(module, import_resolver, crate_types); for item in items.iter() { @@ -2149,7 +2154,7 @@ fn walk_ast_second_pass<'a>(ast_storage: &'a FullLibraryAST, crate_types: &Crate } fn walk_private_mod<'a>(ast_storage: &'a FullLibraryAST, orig_crate: &str, module: String, items: &'a syn::ItemMod, crate_types: &mut CrateTypes<'a>) { - let import_resolver = ImportResolver::new(orig_crate, &ast_storage.dependencies, &module, &items.content.as_ref().unwrap().1); + let import_resolver = ImportResolver::new(orig_crate, ast_storage, &module, &items.content.as_ref().unwrap().1); for item in items.content.as_ref().unwrap().1.iter() { match item { syn::Item::Mod(m) => walk_private_mod(ast_storage, orig_crate, format!("{}::{}", module, m.ident), m, crate_types), @@ -2178,7 +2183,7 @@ fn walk_ast_first_pass<'a>(ast_storage: &'a FullLibraryAST, crate_types: &mut Cr let ASTModule { ref attrs, ref items, submods: _ } = astmod; assert_eq!(export_status(&attrs), ExportStatus::Export); let orig_crate = module.splitn(2, "::").next().unwrap(); - let import_resolver = ImportResolver::new(orig_crate, &ast_storage.dependencies, module, items); + let import_resolver = ImportResolver::new(orig_crate, ast_storage, module, items); for item in items.iter() { match item {