X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=c-bindings-gen%2Fsrc%2Ftypes.rs;h=51a5dfcfd0a60207b36303ca7f08b56f03e7894f;hb=291aea2200e01843623a67d42112500b1810d276;hp=aebeb487ece66605a3770677b9d386041bc29a13;hpb=defa610aab6b181a88423c8a67cfd24bbea6e05e;p=ldk-c-bindings diff --git a/c-bindings-gen/src/types.rs b/c-bindings-gen/src/types.rs index aebeb48..51a5dfc 100644 --- a/c-bindings-gen/src/types.rs +++ b/c-bindings-gen/src/types.rs @@ -352,7 +352,7 @@ impl<'a, 'p: 'a> GenericTypes<'a, 'p> { } } -trait ResolveType<'a> { fn resolve_type(&'a self, ty: &'a syn::Type) -> &'a syn::Type; } +pub trait ResolveType<'a> { fn resolve_type(&'a self, ty: &'a syn::Type) -> &'a syn::Type; } impl<'a, 'b, 'c: 'a + 'b> ResolveType<'c> for Option<&GenericTypes<'a, 'b>> { fn resolve_type(&'c self, ty: &'c syn::Type) -> &'c syn::Type { if let Some(us) = self { @@ -513,14 +513,7 @@ impl<'mod_lifetime, 'crate_lft: 'mod_lifetime> ImportResolver<'mod_lifetime, 'cr }, syn::Item::Type(t) if export_status(&t.attrs) == ExportStatus::Export => { if let syn::Visibility::Public(_) = t.vis { - let mut process_alias = true; - for tok in t.generics.params.iter() { - if let syn::GenericParam::Lifetime(_) = tok {} - else { process_alias = false; } - } - if process_alias { - declared.insert(t.ident.clone(), DeclType::StructImported { generics: &t.generics }); - } + declared.insert(t.ident.clone(), DeclType::StructImported { generics: &t.generics }); } }, syn::Item::Enum(e) => { @@ -723,6 +716,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()); @@ -738,6 +732,8 @@ 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, + /// structs that weren't exposed + pub priv_structs: HashMap, /// Enums which are mapped as C enums with conversion functions pub mirrored_enums: HashMap, /// Traits which are mapped as a pointer + jump table @@ -767,7 +763,7 @@ impl<'a> CrateTypes<'a> { CrateTypes { 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()), + templates_defined: RefCell::new(HashMap::default()), priv_structs: HashMap::new(), clonable_types: RefCell::new(initial_clonable_types()), trait_impls: HashMap::new(), template_file: RefCell::new(template_file), lib_ast: &libast, } @@ -776,6 +772,7 @@ impl<'a> CrateTypes<'a> { self.clonable_types.borrow_mut().insert(object); } pub fn is_clonable(&self, object: &str) -> bool { + object.starts_with("&'static ") || self.clonable_types.borrow().contains(object) } pub fn write_new_template(&self, mangled_container: String, has_destructor: bool, created_container: &[u8]) { @@ -1666,7 +1663,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { write!(w, ">").unwrap(); } pub fn write_rust_type(&self, w: &mut W, generics: Option<&GenericTypes>, t: &syn::Type) { - match t { + match generics.resolve_type(t) { syn::Type::Path(p) => { if p.qself.is_some() { unimplemented!(); @@ -2336,6 +2333,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { } write!(w, "let mut local_{} = (", ident).unwrap(); for (idx, elem) in t.elems.iter().enumerate() { + let real_elem = generics.resolve_type(&elem); let ty_has_inner = { if to_c { // "To C ptr_for_ref" means "return the regular object with @@ -2343,16 +2341,16 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { // if we're about to set ty_has_inner. ptr_for_ref = true; } - if let syn::Type::Reference(t) = elem { + if let syn::Type::Reference(t) = real_elem { if let syn::Type::Path(p) = &*t.elem { self.c_type_has_inner_from_path(&self.resolve_path(&p.path, generics)) } else { false } - } else if let syn::Type::Path(p) = elem { + } else if let syn::Type::Path(p) = real_elem { self.c_type_has_inner_from_path(&self.resolve_path(&p.path, generics)) } else { false } }; if idx != 0 { write!(w, ", ").unwrap(); } - var_prefix(w, elem, generics, is_ref && ty_has_inner, ptr_for_ref, false); + var_prefix(w, real_elem, generics, is_ref && ty_has_inner, ptr_for_ref, false); if is_ref && ty_has_inner { // For ty_has_inner, the regular var_prefix mapping will take a // reference, so deref once here to make sure we keep the original ref. @@ -2364,7 +2362,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { // hope the type is Clonable and use that. write!(w, ".clone()").unwrap(); } - var_suffix(w, elem, generics, is_ref && ty_has_inner, ptr_for_ref, false); + var_suffix(w, real_elem, generics, is_ref && ty_has_inner, ptr_for_ref, false); } write!(w, "){};", if to_c { ".into()" } else { "" }).unwrap(); true @@ -2411,7 +2409,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { if let syn::Type::Reference(r_arg) = t { assert!(!is_ref); // We don't currently support outer reference types for non-primitive inners - if !self.write_c_type_intern(w, &*r_arg.elem, generics, false, false, false, false) { return false; } + if !self.write_c_type_intern(w, &*r_arg.elem, generics, false, false, false, true, true) { return false; } // While write_c_type_intern, above is correct, we don't want to blindly convert a // reference to something stupid, so check that the container is either opaque or a @@ -2429,7 +2427,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { } else { assert!(!is_ref); // We don't currently support outer reference types for non-primitive inners } - if !self.write_c_type_intern(w, t, generics, false, false, false, false) { return false; } + if !self.write_c_type_intern(w, t, generics, false, false, false, true, true) { return false; } } else { // We don't currently support outer reference types for non-primitive inners, // except for the empty tuple. @@ -2438,7 +2436,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { } else { assert!(!is_ref); } - if !self.write_c_type_intern(w, t, generics, false, false, false, false) { return false; } + if !self.write_c_type_intern(w, t, generics, false, false, false, true, true) { return false; } } } true @@ -2537,13 +2535,13 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { if self.is_transparent_container(ident, is_ref, args.iter().map(|a| *a), generics) { if !in_type { 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) { return false; } + 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) { return false; } + 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) { return false; } + if !self.write_c_path_intern(w, &$p_arg.path, generics, true, true, true, false, true) { return false; } } } } else { @@ -2667,13 +2665,16 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { // *** C Type Equivalent Printing *** // ********************************** - fn write_c_path_intern(&self, w: &mut W, path: &syn::Path, generics: Option<&GenericTypes>, is_ref: bool, is_mut: bool, ptr_for_ref: bool, with_ref_lifetime: bool) -> bool { + fn write_c_path_intern(&self, w: &mut W, path: &syn::Path, generics: Option<&GenericTypes>, is_ref: bool, is_mut: bool, ptr_for_ref: bool, with_ref_lifetime: bool, c_ty: bool) -> bool { let full_path = match self.maybe_resolve_path(&path, generics) { Some(path) => path, None => return false }; if let Some(c_type) = self.c_type_from_path(&full_path, is_ref, ptr_for_ref) { write!(w, "{}", c_type).unwrap(); true } else if self.crate_types.traits.get(&full_path).is_some() { + // Note that we always use the crate:: prefix here as we are always referring to a + // concrete object which is of the generated type, it just implements the upstream + // type. if is_ref && ptr_for_ref { write!(w, "*{} crate::{}", if is_mut { "mut" } else { "const" }, full_path).unwrap(); } else if is_ref { @@ -2684,29 +2685,34 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { } true } else if self.crate_types.opaques.get(&full_path).is_some() || self.crate_types.mirrored_enums.get(&full_path).is_some() { + let crate_pfx = if c_ty { "crate::" } else { "" }; if is_ref && ptr_for_ref { // ptr_for_ref implies we're returning the object, which we can't really do for // opaque or mirrored types without box'ing them, which is quite a waste, so return // the actual object itself (for opaque types we'll set the pointer to the actual // type and note that its a reference). - write!(w, "crate::{}", full_path).unwrap(); + write!(w, "{}{}", crate_pfx, full_path).unwrap(); } else if is_ref && with_ref_lifetime { assert!(!is_mut); // If we're concretizing something with a lifetime parameter, we have to pick a // lifetime, of which the only real available choice is `static`, obviously. - write!(w, "&'static ").unwrap(); - self.write_rust_path(w, generics, path); + write!(w, "&'static {}", crate_pfx).unwrap(); + if !c_ty { + self.write_rust_path(w, generics, path); + } else { + write!(w, "{}", full_path).unwrap(); + } } else if is_ref { - write!(w, "&{}crate::{}", if is_mut { "mut " } else { "" }, full_path).unwrap(); + write!(w, "&{}{}{}", if is_mut { "mut " } else { "" }, crate_pfx, full_path).unwrap(); } else { - write!(w, "crate::{}", full_path).unwrap(); + write!(w, "{}{}", crate_pfx, full_path).unwrap(); } true } else { false } } - fn write_c_type_intern(&self, w: &mut W, t: &syn::Type, generics: Option<&GenericTypes>, is_ref: bool, is_mut: bool, ptr_for_ref: bool, with_ref_lifetime: bool) -> bool { + fn write_c_type_intern(&self, w: &mut W, t: &syn::Type, generics: Option<&GenericTypes>, is_ref: bool, is_mut: bool, ptr_for_ref: bool, with_ref_lifetime: bool, c_ty: bool) -> bool { match generics.resolve_type(t) { syn::Type::Path(p) => { if p.qself.is_some() { @@ -2717,24 +2723,24 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { return self.write_c_mangled_container_path(w, Self::path_to_generic_args(&p.path), generics, &full_path, is_ref, is_mut, ptr_for_ref); } if let Some(aliased_type) = self.crate_types.type_aliases.get(&full_path).cloned() { - return self.write_c_type_intern(w, &aliased_type, None, is_ref, is_mut, ptr_for_ref, with_ref_lifetime); + return self.write_c_type_intern(w, &aliased_type, None, is_ref, is_mut, ptr_for_ref, with_ref_lifetime, c_ty); } } - self.write_c_path_intern(w, &p.path, generics, is_ref, is_mut, ptr_for_ref, with_ref_lifetime) + self.write_c_path_intern(w, &p.path, generics, is_ref, is_mut, ptr_for_ref, with_ref_lifetime, c_ty) }, syn::Type::Reference(r) => { - self.write_c_type_intern(w, &*r.elem, generics, true, r.mutability.is_some(), ptr_for_ref, with_ref_lifetime) + self.write_c_type_intern(w, &*r.elem, generics, true, r.mutability.is_some(), ptr_for_ref, with_ref_lifetime, c_ty) }, syn::Type::Array(a) => { if is_ref && is_mut { write!(w, "*mut [").unwrap(); - if !self.write_c_type_intern(w, &a.elem, generics, false, false, ptr_for_ref, with_ref_lifetime) { return false; } + if !self.write_c_type_intern(w, &a.elem, generics, false, false, ptr_for_ref, with_ref_lifetime, c_ty) { return false; } } else if is_ref { write!(w, "*const [").unwrap(); - if !self.write_c_type_intern(w, &a.elem, generics, false, false, ptr_for_ref, with_ref_lifetime) { return false; } + if !self.write_c_type_intern(w, &a.elem, generics, false, false, ptr_for_ref, with_ref_lifetime, c_ty) { return false; } } else { let mut typecheck = Vec::new(); - if !self.write_c_type_intern(&mut typecheck, &a.elem, generics, false, false, ptr_for_ref, with_ref_lifetime) { return false; } + if !self.write_c_type_intern(&mut typecheck, &a.elem, generics, false, false, ptr_for_ref, with_ref_lifetime, c_ty) { return false; } if typecheck[..] != ['u' as u8, '8' as u8] { return false; } } if let syn::Expr::Lit(l) = &a.len { @@ -2760,7 +2766,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { true } 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)); + assert!(self.write_c_path_intern(&mut inner_c_ty, &p.path, generics, true, false, ptr_for_ref, with_ref_lifetime, c_ty)); 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); @@ -2802,7 +2808,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { args.push(syn::GenericArgument::Type((*s.elem).clone())); 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) + 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 { false } }, syn::Type::Tuple(t) => { @@ -2817,16 +2823,16 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { } } pub fn write_c_type(&self, w: &mut W, t: &syn::Type, generics: Option<&GenericTypes>, ptr_for_ref: bool) { - assert!(self.write_c_type_intern(w, t, generics, false, false, ptr_for_ref, false)); + assert!(self.write_c_type_intern(w, t, generics, false, false, ptr_for_ref, false, true)); } pub fn write_c_type_in_generic_param(&self, w: &mut W, t: &syn::Type, generics: Option<&GenericTypes>, ptr_for_ref: bool) { - assert!(self.write_c_type_intern(w, t, generics, false, false, ptr_for_ref, true)); + assert!(self.write_c_type_intern(w, t, generics, false, false, ptr_for_ref, true, false)); } pub fn understood_c_path(&self, p: &syn::Path) -> bool { if p.leading_colon.is_some() { return false; } - self.write_c_path_intern(&mut std::io::sink(), p, None, false, false, false, false) + self.write_c_path_intern(&mut std::io::sink(), p, None, false, false, false, false, true) } pub fn understood_c_type(&self, t: &syn::Type, generics: Option<&GenericTypes>) -> bool { - self.write_c_type_intern(&mut std::io::sink(), t, generics, false, false, false, false) + self.write_c_type_intern(&mut std::io::sink(), t, generics, false, false, false, false, true) } }