}
pub fn assert_simple_bound(bound: &syn::TraitBound) {
- if bound.paren_token.is_some() || bound.lifetimes.is_some() { unimplemented!(); }
+ if bound.paren_token.is_some() { unimplemented!(); }
if let syn::TraitBoundModifier::Maybe(_) = bound.modifier { unimplemented!(); }
}
}
/// Learn the generics in generics in the current context, given a TypeResolver.
- pub fn learn_generics<'b, 'c>(&mut self, generics: &'a syn::Generics, types: &'b TypeResolver<'a, 'c>) -> bool {
+ pub fn learn_generics_with_impls<'b, 'c>(&mut self, generics: &'a syn::Generics, impld_generics: &'a syn::PathArguments, types: &'b TypeResolver<'a, 'c>) -> bool {
let mut new_typed_generics = HashMap::new();
// First learn simple generics...
- for generic in generics.params.iter() {
+ for (idx, generic) in generics.params.iter().enumerate() {
match generic {
syn::GenericParam::Type(type_param) => {
let mut non_lifetimes_processed = false;
if let Some(default) = type_param.default.as_ref() {
assert!(type_param.bounds.is_empty());
self.default_generics.insert(&type_param.ident, (default.clone(), parse_quote!(&#default), parse_quote!(&mut #default)));
+ } else if type_param.bounds.is_empty() {
+ if let syn::PathArguments::AngleBracketed(args) = impld_generics {
+ match &args.args[idx] {
+ syn::GenericArgument::Type(ty) => {
+ self.default_generics.insert(&type_param.ident, (ty.clone(), parse_quote!(&#ty), parse_quote!(&mut #ty)));
+ }
+ _ => unimplemented!(),
+ }
+ }
}
},
_ => {},
for pred in wh.predicates.iter() {
if let syn::WherePredicate::Type(t) = pred {
if let syn::Type::Path(p) = &t.bounded_ty {
+ if first_seg_self(&t.bounded_ty).is_some() && p.path.segments.len() == 1 { continue; }
if p.qself.is_some() { return false; }
if p.path.leading_colon.is_some() { return false; }
let mut p_iter = p.path.segments.iter();
true
}
+ /// Learn the generics in generics in the current context, given a TypeResolver.
+ pub fn learn_generics<'b, 'c>(&mut self, generics: &'a syn::Generics, types: &'b TypeResolver<'a, 'c>) -> bool {
+ self.learn_generics_with_impls(generics, &syn::PathArguments::None, types)
+ }
+
/// Learn the associated types from the trait in the current context.
pub fn learn_associated_types<'b, 'c>(&mut self, t: &'a syn::ItemTrait, types: &'b TypeResolver<'a, 'c>) {
for item in t.items.iter() {
Some(format!("{}::{}{}", self.module_path, first_seg.ident, remaining))
} else if first_seg_is_stdlib(&first_seg_str) || self.dependencies.contains(&first_seg.ident) {
Some(first_seg_str + &remaining)
+ } else if first_seg_str == "crate" {
+ Some(self.crate_name.to_owned() + &remaining)
} else { None }
}
}
"bitcoin::secp256k1::ecdsa::RecoverableSignature" => Some("crate::c_types::RecoverableSignature"),
"bitcoin::secp256k1::SecretKey" if is_ref => Some("*const [u8; 32]"),
"bitcoin::secp256k1::SecretKey" if !is_ref => Some("crate::c_types::SecretKey"),
+ "bitcoin::secp256k1::Scalar" if is_ref => Some("*const crate::c_types::BigEndianScalar"),
+ "bitcoin::secp256k1::Scalar" if !is_ref => Some("crate::c_types::BigEndianScalar"),
+ "bitcoin::secp256k1::ecdh::SharedSecret" if !is_ref => Some("crate::c_types::ThirtyTwoBytes"),
+
"bitcoin::blockdata::script::Script" if is_ref => Some("crate::c_types::u8slice"),
"bitcoin::blockdata::script::Script" if !is_ref => Some("crate::c_types::derived::CVec_u8Z"),
"bitcoin::blockdata::transaction::OutPoint" => Some("crate::lightning::chain::transaction::OutPoint"),
"bitcoin::secp256k1::ecdsa::RecoverableSignature" => Some(""),
"bitcoin::secp256k1::SecretKey" if is_ref => Some("&::bitcoin::secp256k1::SecretKey::from_slice(&unsafe { *"),
"bitcoin::secp256k1::SecretKey" if !is_ref => Some(""),
+ "bitcoin::secp256k1::Scalar" if !is_ref => Some(""),
+ "bitcoin::secp256k1::ecdh::SharedSecret" if !is_ref => Some("::bitcoin::secp256k1::ecdh::SharedSecret::from_bytes("),
+
"bitcoin::blockdata::script::Script" if is_ref => Some("&::bitcoin::blockdata::script::Script::from(Vec::from("),
"bitcoin::blockdata::script::Script" if !is_ref => Some("::bitcoin::blockdata::script::Script::from("),
"bitcoin::blockdata::transaction::Transaction"|"bitcoin::Transaction" if is_ref => Some("&"),
"bitcoin::secp256k1::ecdsa::RecoverableSignature" => Some(".into_rust()"),
"bitcoin::secp256k1::SecretKey" if !is_ref => Some(".into_rust()"),
"bitcoin::secp256k1::SecretKey" if is_ref => Some("}[..]).unwrap()"),
+ "bitcoin::secp256k1::Scalar" if !is_ref => Some(".into_rust()"),
+ "bitcoin::secp256k1::ecdh::SharedSecret" if !is_ref => Some(".data)"),
+
"bitcoin::blockdata::script::Script" if is_ref => Some(".to_slice()))"),
"bitcoin::blockdata::script::Script" if !is_ref => Some(".into_rust())"),
"bitcoin::blockdata::transaction::Transaction"|"bitcoin::Transaction" => Some(".into_bitcoin()"),
"bitcoin::secp256k1::ecdsa::RecoverableSignature" => Some("crate::c_types::RecoverableSignature::from_rust(&"),
"bitcoin::secp256k1::SecretKey" if is_ref => Some(""),
"bitcoin::secp256k1::SecretKey" if !is_ref => Some("crate::c_types::SecretKey::from_rust("),
+ "bitcoin::secp256k1::Scalar" if !is_ref => Some("crate::c_types::BigEndianScalar::from_rust("),
+ "bitcoin::secp256k1::ecdh::SharedSecret" if !is_ref => Some("crate::c_types::ThirtyTwoBytes { data: "),
+
"bitcoin::blockdata::script::Script" if is_ref => Some("crate::c_types::u8slice::from_slice(&"),
"bitcoin::blockdata::script::Script" if !is_ref => Some(""),
"bitcoin::blockdata::transaction::Transaction"|"bitcoin::Transaction" if is_ref => Some("crate::c_types::Transaction::from_bitcoin("),
"bitcoin::secp256k1::ecdsa::RecoverableSignature" => Some(")"),
"bitcoin::secp256k1::SecretKey" if !is_ref => Some(")"),
"bitcoin::secp256k1::SecretKey" if is_ref => Some(".as_ref()"),
+ "bitcoin::secp256k1::Scalar" if !is_ref => Some(")"),
+ "bitcoin::secp256k1::ecdh::SharedSecret" if !is_ref => Some(".secret_bytes() }"),
+
"bitcoin::blockdata::script::Script" if is_ref => Some("[..])"),
"bitcoin::blockdata::script::Script" if !is_ref => Some(".into_bytes().into()"),
"bitcoin::blockdata::transaction::Transaction"|"bitcoin::Transaction" => Some(")"),
if let Some(resolved) = self.maybe_resolve_path(&p.path, generics) {
if self.c_type_has_inner_from_path(&resolved) { return true; }
if self.is_primitive(&resolved) { return false; }
- if self.c_type_from_path(&resolved, false, false).is_some() { true } else { false }
+ // We want to move to using `Option_` mappings where possible rather than
+ // manual mappings, as it makes downstream bindings simpler and is more
+ // clear for users. Thus, we default to false but override for a few
+ // types which had mappings defined when we were avoiding the `Option_`s.
+ match &resolved as &str {
+ "lightning::ln::PaymentSecret" => true,
+ "lightning::ln::PaymentHash" => true,
+ "lightning::ln::PaymentPreimage" => true,
+ "lightning::ln::channelmanager::PaymentId" => true,
+ "bitcoin::hash_types::BlockHash" => true,
+ "secp256k1::PublicKey"|"bitcoin::secp256k1::PublicKey" => true,
+ _ => false,
+ }
} else { unimplemented!(); }
},
syn::Type::Tuple(_) => false,
(".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() {
+ } else if !self.is_transparent_container("Option", is_ref, [single_contained.unwrap()].iter().map(|a| *a), generics) {
if self.is_primitive(&inner_path) || (!is_contained_ref && !is_ref) || only_contained_has_inner {
let inner_name = self.get_c_mangled_container_type(vec![single_contained.unwrap()], generics, "Option").unwrap();
return Some(("if ", vec![
}
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 elems.is_empty() {
+ return Some(("if ", vec![
+ (format!(".is_none() {{ {}::None }} else {{ {}::Some /* ",
+ inner_name, inner_name), format!(""))
+ ], " */ }", ContainerPrefixLocation::PerConv));
+ } else {
+ return Some(("if ", vec![
+ (format!(".is_none() {{ {}::None }} else {{ {}::Some(",
+ inner_name, inner_name), format!("({}.unwrap())", var_access))
+ ], ") }", ContainerPrefixLocation::PerConv));
+ }
}
if let syn::Type::Reference(syn::TypeReference { elem, .. }) = t {
if let syn::Type::Slice(_) = &**elem {
write!(w, "{}", sliceconv(false, None)).unwrap();
}
}
+ } else if let syn::Type::Array(_) = &*s.elem {
+ write!(w, "{}", sliceconv(false, Some(".map(|a| *a)"))).unwrap();
} else { unimplemented!(); }
},
syn::Type::Tuple(t) => {
ptr_for_ref = true;
convert_container!("Slice", 1, || ty.iter());
unimplemented!("convert_container should return true as container_lookup should succeed for slices");
+ } else if let syn::Type::Array(_) = &*s.elem {
+ is_ref = false;
+ ptr_for_ref = true;
+ let arr_elem = [(*s.elem).clone()];
+ convert_container!("Slice", 1, || arr_elem.iter());
+ unimplemented!("convert_container should return true as container_lookup should succeed for slices");
} else { unimplemented!() }
},
syn::Type::Tuple(t) => {
let mut segments = syn::punctuated::Punctuated::new();
segments.push(parse_quote!(Vec<#args>));
self.write_c_type_intern(w, &syn::Type::Path(syn::TypePath { qself: None, path: syn::Path { leading_colon: None, segments } }), generics, false, is_mut, ptr_for_ref, with_ref_lifetime, c_ty)
+ } else if let syn::Type::Array(a) = &*s.elem {
+ if let syn::Expr::Lit(l) = &a.len {
+ if let syn::Lit::Int(i) = &l.lit {
+ let mut buf = Vec::new();
+ self.write_rust_type(&mut buf, generics, &*a.elem, false);
+ let arr_ty = String::from_utf8(buf).unwrap();
+
+ let arr_str = format!("[{}; {}]", arr_ty, i.base10_digits());
+ let ty = self.c_type_from_path(&arr_str, false, ptr_for_ref).unwrap()
+ .rsplitn(2, "::").next().unwrap();
+
+ let mangled_container = format!("CVec_{}Z", ty);
+ 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 { false }
},
syn::Type::Tuple(t) => {