X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=c-bindings-gen%2Fsrc%2Ftypes.rs;h=e18c46518e03137a6de2c22936e32804a0cf703d;hb=5aaf753ce9c1b52d2b8ae46c93b0e57e7ac0f4fc;hp=6e60f82a7a3d9e36e000da84cd6d44fb4bf35f08;hpb=3b25dea8191f380bf5fc3e5744223e326e4ec180;p=ldk-c-bindings diff --git a/c-bindings-gen/src/types.rs b/c-bindings-gen/src/types.rs index 6e60f82..e18c465 100644 --- a/c-bindings-gen/src/types.rs +++ b/c-bindings-gen/src/types.rs @@ -215,7 +215,7 @@ impl<'a, 'p: 'a> GenericTypes<'a, 'p> { 'bound_loop: for bound in type_param.bounds.iter() { if let syn::TypeParamBound::Trait(trait_bound) = bound { if let Some(ident) = single_ident_generic_path_to_ident(&trait_bound.path) { - match &format!("{}", ident) as &str { "Send" => continue, "Sync" => continue, _ => {} } + match &format!("{}", ident) as &str { "Send" => continue, "Sync" => continue, "Sized" => continue, _ => {} } } if path_matches_nongeneric(&trait_bound.path, &["core", "clone", "Clone"]) { continue; } @@ -352,7 +352,12 @@ impl<'a, 'p: 'a> GenericTypes<'a, 'p> { } } else { unimplemented!(); } for bound in bounds_iter { - if let syn::TypeParamBound::Trait(_) = bound { unimplemented!(); } + if let syn::TypeParamBound::Trait(t) = bound { + // We only allow for `?Sized` here. + if let syn::TraitBoundModifier::Maybe(_) = t.modifier {} else { panic!(); } + assert_eq!(t.path.segments.len(), 1); + assert_eq!(format!("{}", t.path.segments[0].ident), "Sized"); + } } break; }, @@ -474,9 +479,12 @@ impl<'mod_lifetime, 'crate_lft: 'mod_lifetime> ImportResolver<'mod_lifetime, 'cr 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); - path.push(parse_quote!(#crate_name_ident)); + new_path = format!("{}::{}{}", module_path, $ident, $path_suffix); + for module in module_path.split("::") { + path.push(syn::PathSegment { ident: syn::Ident::new(module, Span::call_site()), arguments: syn::PathArguments::None }); + } + let ident_str = format_ident!("{}", $ident); + path.push(parse_quote!(#ident_str)); } else if format!("{}", $ident) == "self" { let mut path_iter = partial_path.rsplitn(2, "::"); path_iter.next().unwrap(); @@ -586,13 +594,8 @@ impl<'mod_lifetime, 'crate_lft: 'mod_lifetime> ImportResolver<'mod_lifetime, 'cr } }, syn::Item::Trait(t) => { - match export_status(&t.attrs) { - ExportStatus::Export|ExportStatus::NotImplementable => { - if let syn::Visibility::Public(_) = t.vis { - declared.insert(t.ident.clone(), DeclType::Trait(t)); - } - }, - _ => continue, + if let syn::Visibility::Public(_) = t.vis { + declared.insert(t.ident.clone(), DeclType::Trait(t)); } }, syn::Item::Mod(m) => { @@ -856,6 +859,8 @@ pub struct CrateTypes<'a> { clonable_types: RefCell>, /// Key impls Value pub trait_impls: HashMap>, + /// Value impls Key + pub traits_impld: HashMap>, /// The full set of modules in the crate(s) pub lib_ast: &'a FullLibraryAST, } @@ -866,7 +871,8 @@ impl<'a> CrateTypes<'a> { opaques: HashMap::new(), mirrored_enums: HashMap::new(), traits: HashMap::new(), type_aliases: HashMap::new(), reverse_alias_map: HashMap::new(), templates_defined: RefCell::new(HashMap::default()), priv_structs: HashMap::new(), - clonable_types: RefCell::new(initial_clonable_types()), trait_impls: HashMap::new(), + clonable_types: RefCell::new(initial_clonable_types()), + trait_impls: HashMap::new(), traits_impld: HashMap::new(), template_file: RefCell::new(template_file), lib_ast: &libast, } } @@ -1452,7 +1458,6 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { fn empty_val_check_suffix_from_path(&self, full_path: &str) -> Option<&str> { match full_path { - "lightning::ln::PaymentSecret" => Some(".data == [0; 32]"), "secp256k1::PublicKey"|"bitcoin::secp256k1::PublicKey" => Some(".is_null()"), "bitcoin::secp256k1::ecdsa::Signature" => Some(".is_null()"), _ => None @@ -1532,11 +1537,6 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { // 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"|"bitcoin::BlockHash" => true, "secp256k1::PublicKey"|"bitcoin::secp256k1::PublicKey" => true, _ => false, } @@ -1993,19 +1993,6 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { } } - fn is_real_type_array(&self, resolved_type: &str) -> Option { - if let Some(real_ty) = self.c_type_from_path(&resolved_type, true, false) { - if real_ty.ends_with("]") && real_ty.starts_with("*const [u8; ") { - let mut split = real_ty.split("; "); - split.next().unwrap(); - let tail_str = split.next().unwrap(); - assert!(split.next().is_none()); - let len = usize::from_str_radix(&tail_str[..tail_str.len() - 1], 10).unwrap(); - Some(parse_quote!([u8; #len])) - } else { None } - } else { None } - } - /// Prints a suffix to determine if a variable is empty (ie was set by write_empty_rust_val). /// See EmptyValExpectedTy for information on return types. fn write_empty_rust_val_check_suffix(&self, generics: Option<&GenericTypes>, w: &mut W, t: &syn::Type) -> EmptyValExpectedTy { @@ -2015,9 +2002,6 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { }, syn::Type::Path(p) => { let resolved = self.resolve_path(&p.path, generics); - if let Some(arr_ty) = self.is_real_type_array(&resolved) { - return self.write_empty_rust_val_check_suffix(generics, w, &arr_ty); - } if self.crate_types.opaques.get(&resolved).is_some() { write!(w, ".inner.is_null()").unwrap(); EmptyValExpectedTy::NonPointer @@ -2145,7 +2129,19 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { if let Some(decl_type) = self.types.maybe_resolve_declared(ident) { decl_lookup(w, decl_type, &self.maybe_resolve_ident(ident).unwrap(), is_ref, is_mut); } else { unimplemented!(); } - } else { unimplemented!(); } + } else { + if let Some(trait_impls) = self.crate_types.traits_impld.get(&resolved_path) { + if trait_impls.len() == 1 { + // If this is a no-export'd crate and there's only one implementation + // in the whole crate, just treat it as a reference to whatever the + // implementor is. + let implementor = self.crate_types.opaques.get(&trait_impls[0]).unwrap(); + decl_lookup(w, &DeclType::StructImported { generics: &implementor.1 }, &trait_impls[0], true, is_mut); + return; + } + } + unimplemented!(); + } }, syn::Type::Array(a) => { if let syn::Type::Path(p) = &*a.elem { @@ -2807,12 +2803,8 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { if self.c_type_has_inner_from_path(&subtype) { if !self.write_c_path_intern(w, &$p_arg.path, generics, is_ref, is_mut, ptr_for_ref, false, true) { return false; } } else { - if let Some(arr_ty) = self.is_real_type_array(&subtype) { - if !self.write_c_type_intern(w, &arr_ty, generics, false, true, false, false, true) { return false; } - } else { - // Option needs to be converted to a *mut T, ie mut ptr-for-ref - if !self.write_c_path_intern(w, &$p_arg.path, generics, true, true, true, false, true) { return false; } - } + // Option needs to be converted to a *mut T, ie mut ptr-for-ref + if !self.write_c_path_intern(w, &$p_arg.path, generics, true, true, true, false, true) { return false; } } } else { write!(w, "{}", $p_arg.path.segments.last().unwrap().ident).unwrap(); @@ -2987,6 +2979,18 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { } true } else { + if let Some(trait_impls) = self.crate_types.traits_impld.get(&full_path) { + if trait_impls.len() == 1 { + // If this is a no-export'd crate and there's only one implementation in the + // whole crate, just treat it as a reference to whatever the implementor is. + if with_ref_lifetime { + write!(w, "&'static crate::{}", trait_impls[0]).unwrap(); + } else { + write!(w, "&crate::{}", trait_impls[0]).unwrap(); + } + return true; + } + } false } }