X-Git-Url: http://git.bitcoin.ninja/index.cgi?p=ldk-c-bindings;a=blobdiff_plain;f=c-bindings-gen%2Fsrc%2Ftypes.rs;h=346f588221fa91e0d50a8ee75014f3d60775e799;hp=5fc90b1ff29fbcd478a50cf1389e174954540ab0;hb=11cd55b6baf2c94a44f0cd24774f0d822ff90d66;hpb=690a087df3712fc4aa64521e6a9beb4a29f876eb diff --git a/c-bindings-gen/src/types.rs b/c-bindings-gen/src/types.rs index 5fc90b1..346f588 100644 --- a/c-bindings-gen/src/types.rs +++ b/c-bindings-gen/src/types.rs @@ -110,8 +110,7 @@ pub fn export_status(attrs: &[syn::Attribute]) -> ExportStatus { } if all_test { return ExportStatus::TestOnly; } } - } else if i == "test" || i == "feature" { - // If its cfg(feature(...)) we assume its test-only + } else if i == "test" { return ExportStatus::TestOnly; } } @@ -724,6 +723,7 @@ fn initial_clonable_types() -> HashSet { let mut res = HashSet::new(); res.insert("crate::c_types::u5".to_owned()); res.insert("crate::c_types::ThirtyTwoBytes".to_owned()); + res.insert("crate::c_types::SecretKey".to_owned()); res.insert("crate::c_types::PublicKey".to_owned()); res.insert("crate::c_types::Transaction".to_owned()); res.insert("crate::c_types::TxOut".to_owned()); @@ -828,7 +828,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { // ************************************************* /// Returns true we if can just skip passing this to C entirely - fn skip_path(&self, full_path: &str) -> bool { + pub fn skip_path(&self, full_path: &str) -> bool { full_path == "bitcoin::secp256k1::Secp256k1" || full_path == "bitcoin::secp256k1::Signing" || full_path == "bitcoin::secp256k1::Verification" @@ -888,7 +888,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { "core::convert::Infallible" => Some("crate::c_types::NotConstructable"), - "bech32::u5" => Some("crate::c_types::u5"), + "bitcoin::bech32::u5"|"bech32::u5" => Some("crate::c_types::u5"), "core::num::NonZeroU8" => Some("u8"), "bitcoin::secp256k1::key::PublicKey"|"bitcoin::secp256k1::PublicKey"|"secp256k1::key::PublicKey" @@ -966,10 +966,10 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { "core::convert::Infallible" => Some("panic!(\"You must never construct a NotConstructable! : "), - "std::time::Duration"|"core::time::Duration" => Some("std::time::Duration::from_secs("), + "std::time::Duration"|"core::time::Duration" => Some("core::time::Duration::from_secs("), "std::time::SystemTime" => Some("(::std::time::SystemTime::UNIX_EPOCH + std::time::Duration::from_secs("), - "bech32::u5" => Some(""), + "bitcoin::bech32::u5"|"bech32::u5" => Some(""), "core::num::NonZeroU8" => Some("core::num::NonZeroU8::new("), "bitcoin::secp256k1::key::PublicKey"|"bitcoin::secp256k1::PublicKey"|"secp256k1::key::PublicKey" @@ -1051,7 +1051,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { "std::time::Duration"|"core::time::Duration" => Some(")"), "std::time::SystemTime" => Some("))"), - "bech32::u5" => Some(".into()"), + "bitcoin::bech32::u5"|"bech32::u5" => Some(".into()"), "core::num::NonZeroU8" => Some(").expect(\"Value must be non-zero\")"), "bitcoin::secp256k1::key::PublicKey"|"bitcoin::secp256k1::PublicKey"|"secp256k1::key::PublicKey" @@ -1134,11 +1134,11 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { "std::time::Duration"|"core::time::Duration" => Some(""), "std::time::SystemTime" => Some(""), "std::io::Error" if !is_ref => Some("crate::c_types::IOError::from_rust("), - "core::fmt::Arguments" => Some("format!(\"{}\", "), + "core::fmt::Arguments" => Some("alloc::format!(\"{}\", "), "core::convert::Infallible" => Some("panic!(\"Cannot construct an Infallible: "), - "bech32::u5" => Some(""), + "bitcoin::bech32::u5"|"bech32::u5" => Some(""), "bitcoin::secp256k1::key::PublicKey"|"bitcoin::secp256k1::PublicKey"|"secp256k1::key::PublicKey" => Some("crate::c_types::PublicKey::from_rust(&"), @@ -1211,7 +1211,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { "core::convert::Infallible" => Some("\")"), - "bech32::u5" => Some(".into()"), + "bitcoin::bech32::u5"|"bech32::u5" => Some(".into()"), "bitcoin::secp256k1::key::PublicKey"|"bitcoin::secp256k1::PublicKey"|"secp256k1::key::PublicKey" => Some(")"), @@ -1269,7 +1269,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { /// TODO: We should never need to use this! fn real_rust_type_mapping<'equiv>(&self, thing: &'equiv str) -> &'equiv str { match thing { - "lightning::io::Read" => "std::io::Read", + "lightning::io::Read" => "crate::c_types::io::Read", _ => thing, } } @@ -1297,6 +1297,22 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { assert!(args.next().is_none()); match inner { syn::Type::Reference(_) => true, + syn::Type::Array(a) => { + if let syn::Expr::Lit(l) = &a.len { + if let syn::Lit::Int(i) = &l.lit { + if i.base10_digits().parse::().unwrap() >= 32 { + let mut buf = Vec::new(); + self.write_rust_type(&mut buf, generics, &a.elem); + let ty = String::from_utf8(buf).unwrap(); + ty == "u8" + } else { + // Blindly assume that if we're trying to create an empty value for an + // array < 32 entries that all-0s may be a valid state. + unimplemented!(); + } + } else { unimplemented!(); } + } else { unimplemented!(); } + }, syn::Type::Path(p) => { if let Some(resolved) = self.maybe_resolve_path(&p.path, generics) { if self.c_type_has_inner_from_path(&resolved) { return true; } @@ -1365,12 +1381,12 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { let is_inner_ref = if let Some(syn::Type::Reference(_)) = single_contained { true } else { false }; if is_ref { return Some(("if ", vec![ - (".is_none() { std::ptr::null() } else { ObjOps::nonnull_ptr_to_inner(".to_owned(), + (".is_none() { core::ptr::null() } else { ObjOps::nonnull_ptr_to_inner(".to_owned(), format!("({}{}.unwrap())", var_access, if is_inner_ref { "" } else { ".as_ref()" })) ], ") }", ContainerPrefixLocation::OutsideConv)); } else { return Some(("if ", vec![ - (".is_none() { std::ptr::null_mut() } else { ".to_owned(), format!("({}.unwrap())", var_access)) + (".is_none() { core::ptr::null_mut() } else { ".to_owned(), format!("({}.unwrap())", var_access)) ], " }", ContainerPrefixLocation::OutsideConv)); } } else if self.is_primitive(&inner_path) || self.c_type_from_path(&inner_path, false, false).is_none() { @@ -1386,6 +1402,14 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { } } if let Some(t) = single_contained { + if let syn::Type::Tuple(syn::TypeTuple { elems, .. }) = t { + assert!(elems.is_empty()); + let inner_name = self.get_c_mangled_container_type(vec![single_contained.unwrap()], generics, "Option").unwrap(); + return Some(("if ", vec![ + (format!(".is_none() {{ {}::None }} else {{ {}::Some /*", + inner_name, inner_name), format!("")) + ], " */}", ContainerPrefixLocation::PerConv)); + } if let syn::Type::Reference(syn::TypeReference { elem, .. }) = t { if let syn::Type::Slice(_) = &**elem { return Some(("if ", vec![ @@ -1696,7 +1720,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { syn::Type::Path(p) => { let resolved = self.resolve_path(&p.path, generics); if self.crate_types.opaques.get(&resolved).is_some() { - write!(w, "crate::{} {{ inner: std::ptr::null_mut(), is_owned: true }}", resolved).unwrap(); + write!(w, "crate::{} {{ inner: core::ptr::null_mut(), is_owned: true }}", resolved).unwrap(); } else { // Assume its a manually-mapped C type, where we can just define an null() fn write!(w, "{}::null()", self.c_type_from_path(&resolved, false, false).unwrap()).unwrap(); @@ -1772,7 +1796,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { syn::Type::Slice(_) => { // Option<[]> always implies that we want to treat len() == 0 differently from // None, so we always map an Option<[]> into a pointer. - write!(w, " == std::ptr::null_mut()").unwrap(); + write!(w, " == core::ptr::null_mut()").unwrap(); EmptyValExpectedTy::ReferenceAsPointer }, _ => unimplemented!(), @@ -1890,8 +1914,11 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { // This may result in some outputs not compiling. if let syn::Type::Path(p) = &*s.elem { let resolved = self.resolve_path(&p.path, generics); - assert!(self.is_primitive(&resolved)); - write!(w, "{}", path_lookup("[u8]", is_ref, ptr_for_ref).unwrap()).unwrap(); + if self.is_primitive(&resolved) { + write!(w, "{}", path_lookup("[u8]", is_ref, ptr_for_ref).unwrap()).unwrap(); + } else { + write!(w, "{}", sliceconv(true, None)).unwrap(); + } } else if let syn::Type::Reference(r) = &*s.elem { if let syn::Type::Path(p) = &*r.elem { write!(w, "{}", sliceconv(self.c_type_has_inner_from_path(&self.resolve_path(&p.path, generics)), None)).unwrap(); @@ -2238,12 +2265,24 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { syn::Type::Slice(s) => { if let syn::Type::Path(p) = &*s.elem { let resolved = self.resolve_path(&p.path, generics); - assert!(self.is_primitive(&resolved)); - let slice_path = format!("[{}]", resolved); - if let Some((prefix, suffix)) = path_lookup(&slice_path, true) { - write!(w, "let mut local_{} = {}{}{};", ident, prefix, var, suffix).unwrap(); - true - } else { false } + if self.is_primitive(&resolved) { + let slice_path = format!("[{}]", resolved); + if let Some((prefix, suffix)) = path_lookup(&slice_path, true) { + write!(w, "let mut local_{} = {}{}{};", ident, prefix, var, suffix).unwrap(); + true + } else { false } + } else { + let tyref = [&*s.elem]; + if to_c { + // If we're converting from a slice to a Vec, assume we can clone the + // elements and clone them into a new Vec first. Next we'll walk the + // new Vec here and convert them to C types. + write!(w, "let mut local_{}_clone = Vec::new(); local_{}_clone.extend_from_slice({}); let mut {} = local_{}_clone; ", ident, ident, ident, ident, ident).unwrap(); + } + is_ref = false; + convert_container!("Vec", 1, || tyref.iter().map(|t| generics.resolve_type(*t))); + unimplemented!("convert_container should return true as container_lookup should succeed for slices"); + } } else if let syn::Type::Reference(ty) = &*s.elem { let tyref = if from_ownable_ref || !to_c { [&*ty.elem] } else { [&*s.elem] }; is_ref = true; @@ -2393,7 +2432,13 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { } if !self.write_c_type_intern(w, t, generics, false, false, false, false) { return false; } } else { - assert!(!is_ref); // We don't currently support outer reference types for non-primitive inners + // We don't currently support outer reference types for non-primitive inners, + // except for the empty tuple. + if let syn::Type::Tuple(t_arg) = t { + assert!(t_arg.elems.len() == 0 || !is_ref); + } else { + assert!(!is_ref); + } if !self.write_c_type_intern(w, t, generics, false, false, false, false) { return false; } } } @@ -2582,8 +2627,15 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { if !self.is_primitive(&resolved) { return false; } if let syn::Expr::Lit(syn::ExprLit { lit: syn::Lit::Int(len), .. }) = &a.len { if self.c_type_from_path(&format!("[{}; {}]", resolved, len.base10_digits()), is_ref, ptr_for_ref).is_none() { return false; } - write!(w, "_{}{}", resolved, len.base10_digits()).unwrap(); - write!(mangled_type, "_{}{}", resolved, len.base10_digits()).unwrap(); + if in_type || args.len() != 1 { + write!(w, "_{}{}", resolved, len.base10_digits()).unwrap(); + write!(mangled_type, "_{}{}", resolved, len.base10_digits()).unwrap(); + } else { + let arrty = format!("[{}; {}]", resolved, len.base10_digits()); + let realty = self.c_type_from_path(&arrty, is_ref, ptr_for_ref).unwrap_or(&arrty); + write!(w, "{}", realty).unwrap(); + write!(mangled_type, "{}", realty).unwrap(); + } } else { return false; } } else { return false; } }, @@ -2707,7 +2759,17 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { if self.is_primitive(&resolved) { write!(w, "{}::{}slice", Self::container_templ_path(), resolved).unwrap(); true - } else { false } + } else { + let mut inner_c_ty = Vec::new(); + assert!(self.write_c_path_intern(&mut inner_c_ty, &p.path, generics, true, false, ptr_for_ref, with_ref_lifetime)); + if self.is_clonable(&String::from_utf8(inner_c_ty).unwrap()) { + if let Some(id) = p.path.get_ident() { + let mangled_container = format!("CVec_{}Z", id); + write!(w, "{}::{}", Self::generated_container_path(), mangled_container).unwrap(); + self.check_create_container(mangled_container, "Vec", vec![&*s.elem], generics, false) + } else { false } + } else { false } + } } else if let syn::Type::Reference(r) = &*s.elem { if let syn::Type::Path(p) = &*r.elem { // Slices with "real types" inside are mapped as the equivalent non-ref Vec