X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=c-bindings-gen%2Fsrc%2Fmain.rs;h=2aeadaffac2e3024d3c92172bc24d82b5b06ca47;hb=a5137ff3bd343300a902be14aa4315fd4ac37353;hp=76938baf2cf7ab44a0cf89b1b65713672d3112e6;hpb=fc3b0daa8d7f08064876aac7bd4981a0b6c827fd;p=ldk-c-bindings diff --git a/c-bindings-gen/src/main.rs b/c-bindings-gen/src/main.rs index 76938ba..2aeadaf 100644 --- a/c-bindings-gen/src/main.rs +++ b/c-bindings-gen/src/main.rs @@ -102,7 +102,7 @@ fn maybe_convert_trait_impl(w: &mut W, trait_path: &syn::Path }, "lightning::util::ser::Readable"|"lightning::util::ser::ReadableArgs"|"lightning::util::ser::MaybeReadable" => { // Create the Result syn::Type - let mut res_ty: syn::Type = parse_quote!(Result<#for_ty, ::ln::msgs::DecodeError>); + let mut res_ty: syn::Type = parse_quote!(Result<#for_ty, lightning::ln::msgs::DecodeError>); writeln!(w, "#[no_mangle]").unwrap(); writeln!(w, "/// Read a {} from a byte array, created by {}_write", for_obj, for_obj).unwrap(); @@ -151,7 +151,7 @@ fn maybe_convert_trait_impl(w: &mut W, trait_path: &syn::Path } else { unreachable!(); } } else { unreachable!(); } } else if t == "lightning::util::ser::MaybeReadable" { - res_ty = parse_quote!(Result, ::ln::msgs::DecodeError>); + res_ty = parse_quote!(Result, lightning::ln::msgs::DecodeError>); } write!(w, ") -> ").unwrap(); types.write_c_type(w, &res_ty, Some(generics), false); @@ -163,7 +163,7 @@ fn maybe_convert_trait_impl(w: &mut W, trait_path: &syn::Path write!(w, "\tlet res: ").unwrap(); // At least in one case we need type annotations here, so provide them. - types.write_rust_type(w, Some(generics), &res_ty); + types.write_rust_type(w, Some(generics), &res_ty, false); if t == "lightning::util::ser::ReadableArgs" { writeln!(w, " = crate::c_types::deserialize_obj_arg(ser, arg_conv);").unwrap(); @@ -484,7 +484,7 @@ fn writeln_trait<'a, 'b, W: std::io::Write>(w: &mut W, t: &'a syn::ItemTrait, ty } _ => panic!("5"), } - $type_resolver.write_rust_type(w, Some(&gen_types), &*arg.ty); + $type_resolver.write_rust_type(w, Some(&gen_types), &*arg.ty, false); } } } @@ -492,7 +492,7 @@ fn writeln_trait<'a, 'b, W: std::io::Write>(w: &mut W, t: &'a syn::ItemTrait, ty match &m.sig.output { syn::ReturnType::Type(_, rtype) => { write!(w, " -> ").unwrap(); - $type_resolver.write_rust_type(w, Some(&gen_types), &*rtype) + $type_resolver.write_rust_type(w, Some(&gen_types), &*rtype, false) }, _ => {}, } @@ -735,6 +735,25 @@ fn writeln_struct<'a, 'b, W: std::io::Write>(w: &mut W, s: &'a syn::ItemStruct, write!(w, "inner_val").unwrap(); types.write_to_c_conversion_inline_suffix(w, &ref_type, Some(&gen_types), true); writeln!(w, "\n}}").unwrap(); + } else { + // If the type isn't reference-able, but is clonable, export a getter that just clones + if types.understood_c_type(&$field.ty, Some(&gen_types)) { + let mut v = Vec::new(); + types.write_c_type(&mut v, &$field.ty, Some(&gen_types), true); + let s = String::from_utf8(v).unwrap(); + if types.is_clonable(&s) { + writeln_arg_docs(w, &$field.attrs, "", types, Some(&gen_types), vec![].drain(..), Some(&$field.ty)); + writeln!(w, "///\n/// Returns a copy of the field.").unwrap(); + write!(w, "#[no_mangle]\npub extern \"C\" fn {}_get_{}(this_ptr: &{}) -> {}", struct_name, $new_name, struct_name, s).unwrap(); + write!(w, " {{\n\tlet mut inner_val = this_ptr.get_native_mut_ref().{}.clone();\n\t", $real_name).unwrap(); + let local_var = types.write_to_c_conversion_new_var(w, &format_ident!("inner_val"), &$field.ty, Some(&gen_types), true); + if local_var { write!(w, "\n\t").unwrap(); } + types.write_to_c_conversion_inline_prefix(w, &$field.ty, Some(&gen_types), true); + write!(w, "inner_val").unwrap(); + types.write_to_c_conversion_inline_suffix(w, &$field.ty, Some(&gen_types), true); + writeln!(w, "\n}}").unwrap(); + } + } } } @@ -928,7 +947,7 @@ fn writeln_impl(w: &mut W, i: &syn::ItemImpl, types: &mut Typ // mappings from a trai defined in a different file, we may mis-resolve or // fail to resolve the mapped types. Thus, we have to construct a new // resolver for the module that the trait was defined in here first. - let trait_resolver = get_module_type_resolver!(full_trait_path, types.crate_libs, types.crate_types); + let mut trait_resolver = get_module_type_resolver!(full_trait_path, types.crate_libs, types.crate_types); gen_types.learn_associated_types(trait_obj, &trait_resolver); let mut impl_associated_types = HashMap::new(); for item in i.items.iter() { @@ -1088,17 +1107,12 @@ fn writeln_impl(w: &mut W, i: &syn::ItemImpl, types: &mut Typ _ => {} } } - if uncallable_function { - let mut trait_resolver = get_module_type_resolver!(full_trait_path, $types.crate_libs, $types.crate_types); - write_method_params(w, &$trait_meth.sig, "c_void", &mut trait_resolver, Some(&meth_gen_types), true, true); - } else { - write_method_params(w, &$m.sig, "c_void", $types, Some(&meth_gen_types), true, true); - } + write_method_params(w, &$trait_meth.sig, "c_void", &mut trait_resolver, Some(&meth_gen_types), true, true); write!(w, " {{\n\t").unwrap(); if uncallable_function { write!(w, "unreachable!();").unwrap(); } else { - write_method_var_decl_body(w, &$m.sig, "", $types, Some(&meth_gen_types), false); + write_method_var_decl_body(w, &$trait_meth.sig, "", &mut trait_resolver, Some(&meth_gen_types), false); let mut takes_self = false; for inp in $m.sig.inputs.iter() { if let syn::FnArg::Receiver(_) = inp { @@ -1128,7 +1142,7 @@ fn writeln_impl(w: &mut W, i: &syn::ItemImpl, types: &mut Typ }, _ => {}, } - write_method_call_params(w, &$m.sig, "", $types, Some(&meth_gen_types), &real_type, false); + write_method_call_params(w, &$trait_meth.sig, "", &mut trait_resolver, Some(&meth_gen_types), &real_type, false); } write!(w, "\n}}\n").unwrap(); if let syn::ReturnType::Type(_, rtype) = &$m.sig.output { @@ -1166,7 +1180,6 @@ fn writeln_impl(w: &mut W, i: &syn::ItemImpl, types: &mut Typ assert!(meth.default.is_some()); let old_gen_types = gen_types; gen_types = GenericTypes::new(Some(resolved_path.clone())); - let mut trait_resolver = get_module_type_resolver!(full_trait_path, types.crate_libs, types.crate_types); impl_meth!(meth, meth, full_trait_path, trait_obj, "", &mut trait_resolver); gen_types = old_gen_types; }, @@ -1594,8 +1607,37 @@ fn writeln_enum<'a, 'b, W: std::io::Write>(w: &mut W, e: &'a syn::ItemEnum, type let mut needs_free = false; let mut constr = Vec::new(); + let mut is_clonable = true; + + for var in e.variants.iter() { + if let syn::Fields::Named(fields) = &var.fields { + needs_free = true; + for field in fields.named.iter() { + if export_status(&field.attrs) == ExportStatus::TestOnly { continue; } + + let mut ty_checks = Vec::new(); + types.write_c_type(&mut ty_checks, &field.ty, Some(&gen_types), false); + if !types.is_clonable(&String::from_utf8(ty_checks).unwrap()) { + is_clonable = false; + } + } + } else if let syn::Fields::Unnamed(fields) = &var.fields { + for field in fields.unnamed.iter() { + let mut ty_checks = Vec::new(); + types.write_c_type(&mut ty_checks, &field.ty, Some(&gen_types), false); + let ty = String::from_utf8(ty_checks).unwrap(); + if ty != "" && !types.is_clonable(&ty) { + is_clonable = false; + } + } + } + } - writeln!(w, "#[must_use]\n#[derive(Clone)]\n#[repr(C)]\npub enum {} {{", e.ident).unwrap(); + if is_clonable { + writeln!(w, "#[derive(Clone)]").unwrap(); + types.crate_types.set_clonable(format!("{}::{}", types.module_path, e.ident)); + } + writeln!(w, "#[must_use]\n#[repr(C)]\npub enum {} {{", e.ident).unwrap(); for var in e.variants.iter() { assert_eq!(export_status(&var.attrs), ExportStatus::Export); // We can't partially-export a mirrored enum writeln_docs(w, &var.attrs, "\t"); @@ -1803,9 +1845,13 @@ fn writeln_enum<'a, 'b, W: std::io::Write>(w: &mut W, e: &'a syn::ItemEnum, type } } - write_conv!(format!("to_native(&self) -> native{}", e.ident), false, true); + if is_clonable { + write_conv!(format!("to_native(&self) -> native{}", e.ident), false, true); + } write_conv!(format!("into_native(self) -> native{}", e.ident), false, false); - write_conv!(format!("from_native(native: &native{}) -> Self", e.ident), true, true); + if is_clonable { + write_conv!(format!("from_native(native: &native{}) -> Self", e.ident), true, true); + } write_conv!(format!("native_into(native: native{}) -> Self", e.ident), true, false); writeln!(w, "}}").unwrap(); @@ -1813,11 +1859,13 @@ fn writeln_enum<'a, 'b, W: std::io::Write>(w: &mut W, e: &'a syn::ItemEnum, type writeln!(w, "/// Frees any resources used by the {}", e.ident).unwrap(); writeln!(w, "#[no_mangle]\npub extern \"C\" fn {}_free(this_ptr: {}) {{ }}", e.ident, e.ident).unwrap(); } - writeln!(w, "/// Creates a copy of the {}", e.ident).unwrap(); - writeln!(w, "#[no_mangle]").unwrap(); - writeln!(w, "pub extern \"C\" fn {}_clone(orig: &{}) -> {} {{", e.ident, e.ident, e.ident).unwrap(); - writeln!(w, "\torig.clone()").unwrap(); - writeln!(w, "}}").unwrap(); + if is_clonable { + writeln!(w, "/// Creates a copy of the {}", e.ident).unwrap(); + writeln!(w, "#[no_mangle]").unwrap(); + writeln!(w, "pub extern \"C\" fn {}_clone(orig: &{}) -> {} {{", e.ident, e.ident, e.ident).unwrap(); + writeln!(w, "\torig.clone()").unwrap(); + writeln!(w, "}}").unwrap(); + } w.write_all(&constr).unwrap(); write_cpp_wrapper(cpp_headers, &format!("{}", e.ident), needs_free, None); }