X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=c-bindings-gen%2Fsrc%2Ftypes.rs;h=fc832f8ef7f212e5e18dd3f07a92ab521bf26297;hb=6728a81b78cec348a99084e841b055424425e27a;hp=224b3ecfcb8caa3905ce45823aaf27abf7b3ff2f;hpb=18dc4eff64fcad567e67dfe11c501a9b4ec7633e;p=ldk-c-bindings diff --git a/c-bindings-gen/src/types.rs b/c-bindings-gen/src/types.rs index 224b3ec..fc832f8 100644 --- a/c-bindings-gen/src/types.rs +++ b/c-bindings-gen/src/types.rs @@ -46,6 +46,10 @@ pub fn get_single_remaining_path_seg<'a, I: Iterator> } else { None } } +pub fn first_seg_is_stdlib(first_seg_str: &str) -> bool { + first_seg_str == "std" || first_seg_str == "core" || first_seg_str == "alloc" +} + pub fn single_ident_generic_path_to_ident(p: &syn::Path) -> Option<&syn::Ident> { if p.segments.len() == 1 { Some(&p.segments.iter().next().unwrap().ident) @@ -367,8 +371,8 @@ impl<'a, 'b, 'c: 'a + 'b> ResolveType<'c> for Option<&GenericTypes<'a, 'b>> { } _ => {}, } - } - ty + us.parent.resolve_type(ty) + } else { ty } } } @@ -377,9 +381,9 @@ impl<'a, 'b, 'c: 'a + 'b> ResolveType<'c> for Option<&GenericTypes<'a, 'b>> { pub enum DeclType<'a> { MirroredEnum, Trait(&'a syn::ItemTrait), - StructImported, + StructImported { generic_param_count: usize }, StructIgnored, - EnumIgnored, + EnumIgnored { generic_param_count: usize }, } pub struct ImportResolver<'mod_lifetime, 'crate_lft: 'mod_lifetime> { @@ -406,6 +410,10 @@ impl<'mod_lifetime, 'crate_lft: 'mod_lifetime> ImportResolver<'mod_lifetime, 'cr for module in super_mod.split("::") { path.push(syn::PathSegment { ident: syn::Ident::new(module, Span::call_site()), arguments: syn::PathArguments::None }); } + } else if partial_path == "" && format!("{}", $ident) == "crate" { + new_path = format!("{}{}", crate_name, $path_suffix); + let crate_name_ident = format_ident!("{}", crate_name); + path.push(parse_quote!(#crate_name_ident)); } else if partial_path == "" && !dependencies.contains(&$ident) { new_path = format!("{}::{}{}", crate_name, $ident, $path_suffix); let crate_name_ident = format_ident!("{}", crate_name); @@ -487,7 +495,7 @@ impl<'mod_lifetime, 'crate_lft: 'mod_lifetime> ImportResolver<'mod_lifetime, 'cr syn::Item::Struct(s) => { if let syn::Visibility::Public(_) = s.vis { match export_status(&s.attrs) { - ExportStatus::Export => { declared.insert(s.ident.clone(), DeclType::StructImported); }, + ExportStatus::Export => { declared.insert(s.ident.clone(), DeclType::StructImported { generic_param_count: s.generics.params.len() }); }, ExportStatus::NoExport => { declared.insert(s.ident.clone(), DeclType::StructIgnored); }, ExportStatus::TestOnly => continue, ExportStatus::NotImplementable => panic!("(C-not implementable) should only appear on traits!"), @@ -502,14 +510,14 @@ impl<'mod_lifetime, 'crate_lft: 'mod_lifetime> ImportResolver<'mod_lifetime, 'cr else { process_alias = false; } } if process_alias { - declared.insert(t.ident.clone(), DeclType::StructImported); + declared.insert(t.ident.clone(), DeclType::StructImported { generic_param_count: t.generics.params.len() }); } } }, syn::Item::Enum(e) => { if let syn::Visibility::Public(_) = e.vis { match export_status(&e.attrs) { - ExportStatus::Export if is_enum_opaque(e) => { declared.insert(e.ident.clone(), DeclType::EnumIgnored); }, + ExportStatus::Export if is_enum_opaque(e) => { declared.insert(e.ident.clone(), DeclType::EnumIgnored { generic_param_count: e.generics.params.len() }); }, ExportStatus::Export => { declared.insert(e.ident.clone(), DeclType::MirroredEnum); }, ExportStatus::NotImplementable => panic!("(C-not implementable) should only appear on traits!"), _ => continue, @@ -600,7 +608,7 @@ impl<'mod_lifetime, 'crate_lft: 'mod_lifetime> ImportResolver<'mod_lifetime, 'cr } } else if let Some(_) = self.priv_modules.get(&first_seg.ident) { Some(format!("{}::{}{}", self.module_path, first_seg.ident, remaining)) - } else if first_seg_str == "std" || first_seg_str == "core" || self.dependencies.contains(&first_seg.ident) { + } else if first_seg_is_stdlib(&first_seg_str) || self.dependencies.contains(&first_seg.ident) { Some(first_seg_str + &remaining) } else { None } } @@ -720,7 +728,7 @@ fn initial_clonable_types() -> HashSet { pub struct CrateTypes<'a> { /// This may contain structs or enums, but only when either is mapped as /// struct X { inner: *mut originalX, .. } - pub opaques: HashMap, + pub opaques: HashMap, /// Enums which are mapped as C enums with conversion functions pub mirrored_enums: HashMap, /// Traits which are mapped as a pointer + jump table @@ -902,11 +910,10 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { "bitcoin::hash_types::Txid"|"bitcoin::hash_types::BlockHash"|"bitcoin_hashes::sha256::Hash" if !is_ref => Some("crate::c_types::ThirtyTwoBytes"), "bitcoin::secp256k1::Message" if !is_ref => Some("crate::c_types::ThirtyTwoBytes"), - "lightning::ln::PaymentHash" if is_ref => Some("*const [u8; 32]"), - "lightning::ln::PaymentHash" if !is_ref => Some("crate::c_types::ThirtyTwoBytes"), - "lightning::ln::PaymentPreimage" if is_ref => Some("*const [u8; 32]"), - "lightning::ln::PaymentPreimage" if !is_ref => Some("crate::c_types::ThirtyTwoBytes"), - "lightning::ln::PaymentSecret" => Some("crate::c_types::ThirtyTwoBytes"), + "lightning::ln::PaymentHash"|"lightning::ln::PaymentPreimage"|"lightning::ln::PaymentSecret"|"lightning::ln::channelmanager::PaymentId" + if is_ref => Some("*const [u8; 32]"), + "lightning::ln::PaymentHash"|"lightning::ln::PaymentPreimage"|"lightning::ln::PaymentSecret"|"lightning::ln::channelmanager::PaymentId" + if !is_ref => Some("crate::c_types::ThirtyTwoBytes"), // Override the default since Records contain an fmt with a lifetime: "lightning::util::logger::Record" => Some("*const std::os::raw::c_char"), @@ -993,7 +1000,9 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { "lightning::ln::PaymentHash" if is_ref => Some("&::lightning::ln::PaymentHash(unsafe { *"), "lightning::ln::PaymentPreimage" if !is_ref => Some("::lightning::ln::PaymentPreimage("), "lightning::ln::PaymentPreimage" if is_ref => Some("&::lightning::ln::PaymentPreimage(unsafe { *"), - "lightning::ln::PaymentSecret" => Some("::lightning::ln::PaymentSecret("), + "lightning::ln::PaymentSecret" if !is_ref => Some("::lightning::ln::PaymentSecret("), + "lightning::ln::channelmanager::PaymentId" if !is_ref => Some("::lightning::ln::channelmanager::PaymentId("), + "lightning::ln::channelmanager::PaymentId" if is_ref=> Some("&::lightning::ln::channelmanager::PaymentId( unsafe { *"), // List of traits we map (possibly during processing of other files): "crate::util::logger::Logger" => Some(""), @@ -1060,11 +1069,10 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { "bitcoin::hash_types::Txid" if is_ref => Some(" }[..]).unwrap()"), "bitcoin::hash_types::Txid" => Some(".data[..]).unwrap()"), "bitcoin::hash_types::BlockHash" if !is_ref => Some(".data[..]).unwrap()"), - "lightning::ln::PaymentHash" if !is_ref => Some(".data)"), - "lightning::ln::PaymentHash" if is_ref => Some(" })"), - "lightning::ln::PaymentPreimage" if !is_ref => Some(".data)"), - "lightning::ln::PaymentPreimage" if is_ref => Some(" })"), - "lightning::ln::PaymentSecret" => Some(".data)"), + "lightning::ln::PaymentHash"|"lightning::ln::PaymentPreimage"|"lightning::ln::PaymentSecret"|"lightning::ln::channelmanager::PaymentId" + if !is_ref => Some(".data)"), + "lightning::ln::PaymentHash"|"lightning::ln::PaymentPreimage"|"lightning::ln::PaymentSecret"|"lightning::ln::channelmanager::PaymentId" + if is_ref => Some(" })"), // List of traits we map (possibly during processing of other files): "crate::util::logger::Logger" => Some(""), @@ -1152,11 +1160,10 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { "bitcoin::hash_types::Txid"|"bitcoin::hash_types::BlockHash"|"bitcoin_hashes::sha256::Hash" if !is_ref => Some("crate::c_types::ThirtyTwoBytes { data: "), "bitcoin::secp256k1::Message" if !is_ref => Some("crate::c_types::ThirtyTwoBytes { data: "), - "lightning::ln::PaymentHash" if is_ref => Some("&"), - "lightning::ln::PaymentHash" if !is_ref => Some("crate::c_types::ThirtyTwoBytes { data: "), - "lightning::ln::PaymentPreimage" if is_ref => Some("&"), - "lightning::ln::PaymentPreimage" => Some("crate::c_types::ThirtyTwoBytes { data: "), - "lightning::ln::PaymentSecret" => Some("crate::c_types::ThirtyTwoBytes { data: "), + "lightning::ln::PaymentHash"|"lightning::ln::PaymentPreimage"|"lightning::ln::PaymentSecret"|"lightning::ln::channelmanager::PaymentId" + if is_ref => Some("&"), + "lightning::ln::PaymentHash"|"lightning::ln::PaymentPreimage"|"lightning::ln::PaymentSecret"|"lightning::ln::channelmanager::PaymentId" + if !is_ref => Some("crate::c_types::ThirtyTwoBytes { data: "), // Override the default since Records contain an fmt with a lifetime: "lightning::util::logger::Record" => Some("local_"), @@ -1225,11 +1232,10 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { "bitcoin::hash_types::Txid"|"bitcoin::hash_types::BlockHash"|"bitcoin_hashes::sha256::Hash" if !is_ref => Some(".into_inner() }"), "bitcoin::secp256k1::Message" if !is_ref => Some(".as_ref().clone() }"), - "lightning::ln::PaymentHash" if is_ref => Some(".0"), - "lightning::ln::PaymentHash" => Some(".0 }"), - "lightning::ln::PaymentPreimage" if is_ref => Some(".0"), - "lightning::ln::PaymentPreimage" => Some(".0 }"), - "lightning::ln::PaymentSecret" => Some(".0 }"), + "lightning::ln::PaymentHash"|"lightning::ln::PaymentPreimage"|"lightning::ln::PaymentSecret"|"lightning::ln::channelmanager::PaymentId" + if is_ref => Some(".0"), + "lightning::ln::PaymentHash"|"lightning::ln::PaymentPreimage"|"lightning::ln::PaymentSecret"|"lightning::ln::channelmanager::PaymentId" + if !is_ref => Some(".0 }"), // Override the default since Records contain an fmt with a lifetime: "lightning::util::logger::Record" => Some(".as_ptr()"), @@ -1369,6 +1375,14 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { } } if let Some(t) = single_contained { + if let syn::Type::Reference(syn::TypeReference { elem, .. }) = t { + if let syn::Type::Slice(_) = &**elem { + return Some(("if ", vec![ + (".is_none() { SmartPtr::null() } else { SmartPtr::from_obj(".to_string(), + format!("({}.unwrap())", var_access)) + ], ") }", ContainerPrefixLocation::PerConv)); + } + } let mut v = Vec::new(); self.write_empty_rust_val(generics, &mut v, t); let s = String::from_utf8(v).unwrap(); @@ -1839,8 +1853,8 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { } } else if let Some(c_type) = path_lookup(&resolved_path, is_ref, ptr_for_ref) { write!(w, "{}", c_type).unwrap(); - } else if self.crate_types.opaques.get(&resolved_path).is_some() { - decl_lookup(w, &DeclType::StructImported, &resolved_path, is_ref, is_mut); + } else if let Some((_, generics)) = self.crate_types.opaques.get(&resolved_path) { + decl_lookup(w, &DeclType::StructImported { generic_param_count: generics.params.len() }, &resolved_path, is_ref, is_mut); } else if self.crate_types.mirrored_enums.get(&resolved_path).is_some() { decl_lookup(w, &DeclType::MirroredEnum, &resolved_path, is_ref, is_mut); } else if let Some(t) = self.crate_types.traits.get(&resolved_path) { @@ -1927,15 +1941,15 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { DeclType::MirroredEnum if is_ref && ptr_for_ref => write!(w, "crate::{}::from_native(", decl_path).unwrap(), DeclType::MirroredEnum if is_ref => write!(w, "&crate::{}::from_native(", decl_path).unwrap(), DeclType::MirroredEnum => write!(w, "crate::{}::native_into(", decl_path).unwrap(), - DeclType::EnumIgnored|DeclType::StructImported if is_ref && ptr_for_ref && from_ptr => + DeclType::EnumIgnored {..}|DeclType::StructImported {..} if is_ref && ptr_for_ref && from_ptr => write!(w, "crate::{} {{ inner: unsafe {{ (", decl_path).unwrap(), - DeclType::EnumIgnored|DeclType::StructImported if is_ref => { + DeclType::EnumIgnored {..}|DeclType::StructImported {..} if is_ref => { if !ptr_for_ref { write!(w, "&").unwrap(); } write!(w, "crate::{} {{ inner: unsafe {{ ObjOps::nonnull_ptr_to_inner((", decl_path).unwrap() }, - DeclType::EnumIgnored|DeclType::StructImported if !is_ref && from_ptr => + DeclType::EnumIgnored {..}|DeclType::StructImported {..} if !is_ref && from_ptr => write!(w, "crate::{} {{ inner: ", decl_path).unwrap(), - DeclType::EnumIgnored|DeclType::StructImported if !is_ref => + DeclType::EnumIgnored {..}|DeclType::StructImported {..} if !is_ref => write!(w, "crate::{} {{ inner: ObjOps::heap_alloc(", decl_path).unwrap(), DeclType::Trait(_) if is_ref => write!(w, "").unwrap(), DeclType::Trait(_) if !is_ref => write!(w, "Into::into(").unwrap(), @@ -1949,15 +1963,20 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { fn write_to_c_conversion_inline_suffix_inner(&self, w: &mut W, t: &syn::Type, generics: Option<&GenericTypes>, is_ref: bool, ptr_for_ref: bool, from_ptr: bool) { self.write_conversion_inline_intern(w, t, generics, is_ref, false, ptr_for_ref, "*/", false, |_, _| ".into()".to_owned(), |a, b, c| self.to_c_conversion_inline_suffix_from_path(a, b, c), - |w, decl_type, _full_path, is_ref, _is_mut| match decl_type { + |w, decl_type, full_path, is_ref, _is_mut| match decl_type { DeclType::MirroredEnum => write!(w, ")").unwrap(), - DeclType::EnumIgnored|DeclType::StructImported if is_ref && ptr_for_ref && from_ptr => - write!(w, " as *const _) as *mut _ }}, is_owned: false }}").unwrap(), - DeclType::EnumIgnored|DeclType::StructImported if is_ref => - write!(w, " as *const _) as *mut _) }}, is_owned: false }}").unwrap(), - DeclType::EnumIgnored|DeclType::StructImported if !is_ref && from_ptr => + DeclType::EnumIgnored { generic_param_count }|DeclType::StructImported { generic_param_count } if is_ref => { + write!(w, " as *const {}<", full_path).unwrap(); + for _ in 0..*generic_param_count { write!(w, "_, ").unwrap(); } + if ptr_for_ref && from_ptr { + write!(w, ">) as *mut _ }}, is_owned: false }}").unwrap(); + } else { + write!(w, ">) as *mut _) }}, is_owned: false }}").unwrap(); + } + }, + DeclType::EnumIgnored {..}|DeclType::StructImported {..} if !is_ref && from_ptr => write!(w, ", is_owned: true }}").unwrap(), - DeclType::EnumIgnored|DeclType::StructImported if !is_ref => write!(w, "), is_owned: true }}").unwrap(), + DeclType::EnumIgnored {..}|DeclType::StructImported {..} if !is_ref => write!(w, "), is_owned: true }}").unwrap(), DeclType::Trait(_) if is_ref => {}, DeclType::Trait(_) => { // This is used when we're converting a concrete Rust type into a C trait @@ -1977,8 +1996,8 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { self.write_conversion_inline_intern(w, t, generics, is_ref, false, false, "() /*", true, |_, _| "&local_".to_owned(), |a, b, _c| self.from_c_conversion_prefix_from_path(a, b), |w, decl_type, _full_path, is_ref, _is_mut| match decl_type { - DeclType::StructImported if is_ref => write!(w, "").unwrap(), - DeclType::StructImported if !is_ref => write!(w, "*unsafe {{ Box::from_raw(").unwrap(), + DeclType::StructImported {..} if is_ref => write!(w, "").unwrap(), + DeclType::StructImported {..} if !is_ref => write!(w, "*unsafe {{ Box::from_raw(").unwrap(), DeclType::MirroredEnum if is_ref => write!(w, "&").unwrap(), DeclType::MirroredEnum => {}, DeclType::Trait(_) => {}, @@ -1998,10 +2017,10 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { }, |a, b, _c| self.from_c_conversion_suffix_from_path(a, b), |w, decl_type, _full_path, is_ref, is_mut| match decl_type { - DeclType::StructImported if is_ref && ptr_for_ref => write!(w, "XXX unimplemented").unwrap(), - DeclType::StructImported if is_mut && is_ref => write!(w, ".get_native_mut_ref()").unwrap(), - DeclType::StructImported if is_ref => write!(w, ".get_native_ref()").unwrap(), - DeclType::StructImported if !is_ref => write!(w, ".take_inner()) }}").unwrap(), + DeclType::StructImported {..} if is_ref && ptr_for_ref => write!(w, "XXX unimplemented").unwrap(), + DeclType::StructImported {..} if is_mut && is_ref => write!(w, ".get_native_mut_ref()").unwrap(), + DeclType::StructImported {..} if is_ref => write!(w, ".get_native_ref()").unwrap(), + DeclType::StructImported {..} if !is_ref => write!(w, ".take_inner()) }}").unwrap(), DeclType::MirroredEnum if is_ref => write!(w, ".to_native()").unwrap(), DeclType::MirroredEnum => write!(w, ".into_native()").unwrap(), DeclType::Trait(_) => {}, @@ -2021,7 +2040,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { } else { None } }, |w, decl_type, _full_path, is_ref, _is_mut| match decl_type { - DeclType::StructImported if !is_ref => write!(w, "").unwrap(), + DeclType::StructImported {..} if !is_ref => write!(w, "").unwrap(), _ => unimplemented!(), }); } @@ -2035,7 +2054,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { }, |a, b, _c| self.from_c_conversion_suffix_from_path(a, b), |w, decl_type, _full_path, is_ref, _is_mut| match decl_type { - DeclType::StructImported if !is_ref => write!(w, ".get_native_ref()").unwrap(), + DeclType::StructImported {..} if !is_ref => write!(w, ".get_native_ref()").unwrap(), _ => unimplemented!(), }); } @@ -2102,7 +2121,8 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { if let Some((prefix, conversions, suffix, prefix_location)) = container_lookup(&$container_type, is_ref && ty_has_inner, only_contained_type, ident, var) { assert_eq!(conversions.len(), $args_len); - write!(w, "let mut local_{}{} = ", ident, if !to_c && needs_ref_map {"_base"} else { "" }).unwrap(); + write!(w, "let mut local_{}{} = ", ident, + if (!to_c && needs_ref_map) || (to_c && $container_type == "Option" && contains_slice) {"_base"} else { "" }).unwrap(); if prefix_location == ContainerPrefixLocation::OutsideConv { var_prefix(w, $args_iter().next().unwrap(), generics, is_ref, ptr_for_ref, true); } @@ -2127,7 +2147,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { write!(w, "ObjOps::heap_alloc(").unwrap(); } - write!(w, "{}{}", if contains_slice { "local_" } else { "" }, if new_var { new_var_name } else { var_access }).unwrap(); + write!(w, "{}{}", if contains_slice && !to_c { "local_" } else { "" }, if new_var { new_var_name } else { var_access }).unwrap(); if prefix_location == ContainerPrefixLocation::PerConv { var_suffix(w, conv_ty, generics, is_ref && ty_has_inner, ptr_for_ref, false); } else if !is_ref && !needs_ref_map && to_c && only_contained_has_inner { @@ -2146,6 +2166,8 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { write!(w, ".map(|a| &a[..])").unwrap(); } write!(w, ";").unwrap(); + } else if to_c && $container_type == "Option" && contains_slice { + write!(w, " let mut local_{} = *local_{}_base;", ident, ident).unwrap(); } return true; } @@ -2665,7 +2687,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { if let syn::Type::Path(p) = &*r.elem { // Slices with "real types" inside are mapped as the equivalent non-ref Vec let resolved = self.resolve_path(&p.path, generics); - let mangled_container = if let Some(ident) = self.crate_types.opaques.get(&resolved) { + let mangled_container = if let Some((ident, _)) = self.crate_types.opaques.get(&resolved) { format!("CVec_{}Z", ident) } else if let Some(en) = self.crate_types.mirrored_enums.get(&resolved) { format!("CVec_{}Z", en.ident) @@ -2679,7 +2701,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { if let syn::Type::Path(p) = &*r2.elem { // Slices with slices with opaque types (with is_owned flags) are mapped as non-ref Vecs let resolved = self.resolve_path(&p.path, generics); - let mangled_container = if let Some(ident) = self.crate_types.opaques.get(&resolved) { + let mangled_container = if let Some((ident, _)) = self.crate_types.opaques.get(&resolved) { format!("CVec_CVec_{}ZZ", ident) } else { return false; }; write!(w, "{}::{}", Self::generated_container_path(), mangled_container).unwrap();