X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=c-bindings-gen%2Fsrc%2Ftypes.rs;h=8b9606dec3fb467a56ced3ef071313d402e5ee0e;hb=995561a6e039d662ca2726ea455de158ffde154f;hp=598552102f3691ba9f50839ad1e6cda673700e54;hpb=2951949623b40708f0c56784a5bd270993da7e31;p=ldk-c-bindings diff --git a/c-bindings-gen/src/types.rs b/c-bindings-gen/src/types.rs index 5985521..8b9606d 100644 --- a/c-bindings-gen/src/types.rs +++ b/c-bindings-gen/src/types.rs @@ -190,7 +190,7 @@ pub struct GenericTypes<'a, 'b> { self_ty: Option, parent: Option<&'b GenericTypes<'b, 'b>>, typed_generics: HashMap<&'a syn::Ident, String>, - default_generics: HashMap<&'a syn::Ident, (syn::Type, syn::Type)>, + default_generics: HashMap<&'a syn::Ident, (syn::Type, syn::Type, syn::Type)>, } impl<'a, 'p: 'a> GenericTypes<'a, 'p> { pub fn new(self_ty: Option) -> Self { @@ -226,20 +226,25 @@ impl<'a, 'p: 'a> GenericTypes<'a, 'p> { if non_lifetimes_processed { return false; } non_lifetimes_processed = true; if path != "std::ops::Deref" && path != "core::ops::Deref" { + let p = string_path_to_syn_path(&path); + let ref_ty = parse_quote!(&#p); + let mut_ref_ty = parse_quote!(&mut #p); + self.default_generics.insert(&type_param.ident, (syn::Type::Path(syn::TypePath { qself: None, path: p }), ref_ty, mut_ref_ty)); new_typed_generics.insert(&type_param.ident, Some(path)); - } else if trait_bound.path.segments.len() == 1 { + } else { // If we're templated on Deref, store // the reference type in `default_generics` which handles full // types and not just paths. if let syn::PathArguments::AngleBracketed(ref args) = trait_bound.path.segments[0].arguments { + assert_eq!(trait_bound.path.segments.len(), 1); for subargument in args.args.iter() { match subargument { syn::GenericArgument::Lifetime(_) => {}, syn::GenericArgument::Binding(ref b) => { if &format!("{}", b.ident) != "Target" { return false; } let default = &b.ty; - self.default_generics.insert(&type_param.ident, (parse_quote!(&#default), parse_quote!(&#default))); + self.default_generics.insert(&type_param.ident, (parse_quote!(&#default), parse_quote!(&#default), parse_quote!(&mut #default))); break 'bound_loop; }, _ => unimplemented!(), @@ -254,7 +259,7 @@ impl<'a, 'p: 'a> GenericTypes<'a, 'p> { } 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))); + self.default_generics.insert(&type_param.ident, (default.clone(), parse_quote!(&#default), parse_quote!(&mut #default))); } }, _ => {}, @@ -287,10 +292,11 @@ impl<'a, 'p: 'a> GenericTypes<'a, 'p> { qself: None, path: string_path_to_syn_path(&resolved) }); let ref_ty = parse_quote!(&#ty); + let mut_ref_ty = parse_quote!(&mut #ty); if types.crate_types.traits.get(&resolved).is_some() { - self.default_generics.insert(p_ident, (ty, ref_ty)); + self.default_generics.insert(p_ident, (ty, ref_ty, mut_ref_ty)); } else { - self.default_generics.insert(p_ident, (ref_ty.clone(), ref_ty)); + self.default_generics.insert(p_ident, (ref_ty.clone(), ref_ty, mut_ref_ty)); } *gen = Some(resolved); @@ -382,16 +388,20 @@ impl<'a, 'b, 'c: 'a + 'b> ResolveType<'c> for Option<&GenericTypes<'a, 'b>> { match ty { syn::Type::Path(p) => { if let Some(ident) = p.path.get_ident() { - if let Some((ty, _)) = us.default_generics.get(ident) { - return ty; + if let Some((ty, _, _)) = us.default_generics.get(ident) { + return self.resolve_type(ty); } } }, - syn::Type::Reference(syn::TypeReference { elem, .. }) => { + syn::Type::Reference(syn::TypeReference { elem, mutability, .. }) => { if let syn::Type::Path(p) = &**elem { if let Some(ident) = p.path.get_ident() { - if let Some((_, refty)) = us.default_generics.get(ident) { - return refty; + if let Some((_, refty, mut_ref_ty)) = us.default_generics.get(ident) { + if mutability.is_some() { + return self.resolve_type(mut_ref_ty); + } else { + return self.resolve_type(refty); + } } } } @@ -1342,7 +1352,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { 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); + self.write_rust_type(&mut buf, generics, &a.elem, false); let ty = String::from_utf8(buf).unwrap(); ty == "u8" } else { @@ -1642,7 +1652,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { } } - fn write_rust_path(&self, w: &mut W, generics_resolver: Option<&GenericTypes>, path: &syn::Path) { + fn write_rust_path(&self, w: &mut W, generics_resolver: Option<&GenericTypes>, path: &syn::Path, with_ref_lifetime: bool, generated_crate_ref: bool) { if let Some(resolved) = self.maybe_resolve_path(&path, generics_resolver) { if self.is_primitive(&resolved) { write!(w, "{}", path.get_ident().unwrap()).unwrap(); @@ -1651,16 +1661,16 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { // checking for "bitcoin" explicitly. if resolved.starts_with("bitcoin::") || Self::in_rust_prelude(&resolved) { write!(w, "{}", resolved).unwrap(); - // If we're printing a generic argument, it needs to reference the crate, otherwise - // the original crate: - } else if self.maybe_resolve_path(&path, None).as_ref() == Some(&resolved) { + } else if !generated_crate_ref { + // If we're printing a generic argument, it needs to reference the crate, otherwise + // the original crate. write!(w, "{}", self.real_rust_type_mapping(&resolved)).unwrap(); } else { write!(w, "crate::{}", resolved).unwrap(); } } if let syn::PathArguments::AngleBracketed(args) = &path.segments.iter().last().unwrap().arguments { - self.write_rust_generic_arg(w, generics_resolver, args.args.iter()); + self.write_rust_generic_arg(w, generics_resolver, args.args.iter(), with_ref_lifetime); } } else { if path.leading_colon.is_some() { @@ -1670,7 +1680,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { if idx != 0 { write!(w, "::").unwrap(); } write!(w, "{}", seg.ident).unwrap(); if let syn::PathArguments::AngleBracketed(args) = &seg.arguments { - self.write_rust_generic_arg(w, generics_resolver, args.args.iter()); + self.write_rust_generic_arg(w, generics_resolver, args.args.iter(), with_ref_lifetime); } } } @@ -1690,7 +1700,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { match bound { syn::TypeParamBound::Trait(tb) => { if tb.paren_token.is_some() || tb.lifetimes.is_some() { unimplemented!(); } - self.write_rust_path(w, generics_resolver, &tb.path); + self.write_rust_path(w, generics_resolver, &tb.path, false, false); }, _ => unimplemented!(), } @@ -1703,38 +1713,46 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { if had_params { write!(w, ">").unwrap(); } } - pub fn write_rust_generic_arg<'b, W: std::io::Write>(&self, w: &mut W, generics_resolver: Option<&GenericTypes>, generics: impl Iterator) { + pub fn write_rust_generic_arg<'b, W: std::io::Write>(&self, w: &mut W, generics_resolver: Option<&GenericTypes>, generics: impl Iterator, with_ref_lifetime: bool) { write!(w, "<").unwrap(); for (idx, arg) in generics.enumerate() { if idx != 0 { write!(w, ", ").unwrap(); } match arg { - syn::GenericArgument::Type(t) => self.write_rust_type(w, generics_resolver, t), + syn::GenericArgument::Type(t) => self.write_rust_type(w, generics_resolver, t, with_ref_lifetime), _ => unimplemented!(), } } write!(w, ">").unwrap(); } - pub fn write_rust_type(&self, w: &mut W, generics: Option<&GenericTypes>, t: &syn::Type) { - match generics.resolve_type(t) { + fn do_write_rust_type(&self, w: &mut W, generics: Option<&GenericTypes>, t: &syn::Type, with_ref_lifetime: bool, force_crate_ref: bool) { + let real_ty = generics.resolve_type(t); + let mut generate_crate_ref = force_crate_ref || t != real_ty; + match real_ty { syn::Type::Path(p) => { if p.qself.is_some() { unimplemented!(); } - self.write_rust_path(w, generics, &p.path); + if let Some(resolved_ty) = self.maybe_resolve_path(&p.path, generics) { + generate_crate_ref |= self.maybe_resolve_path(&p.path, None).as_ref() != Some(&resolved_ty); + if self.crate_types.traits.get(&resolved_ty).is_none() { generate_crate_ref = false; } + } + self.write_rust_path(w, generics, &p.path, with_ref_lifetime, generate_crate_ref); }, syn::Type::Reference(r) => { write!(w, "&").unwrap(); if let Some(lft) = &r.lifetime { write!(w, "'{} ", lft.ident).unwrap(); + } else if with_ref_lifetime { + write!(w, "'static ").unwrap(); } if r.mutability.is_some() { write!(w, "mut ").unwrap(); } - self.write_rust_type(w, generics, &*r.elem); + self.do_write_rust_type(w, generics, &*r.elem, with_ref_lifetime, generate_crate_ref); }, syn::Type::Array(a) => { write!(w, "[").unwrap(); - self.write_rust_type(w, generics, &a.elem); + self.do_write_rust_type(w, generics, &a.elem, with_ref_lifetime, generate_crate_ref); if let syn::Expr::Lit(l) = &a.len { if let syn::Lit::Int(i) = &l.lit { write!(w, "; {}]", i).unwrap(); @@ -1743,20 +1761,24 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { } syn::Type::Slice(s) => { write!(w, "[").unwrap(); - self.write_rust_type(w, generics, &s.elem); + self.do_write_rust_type(w, generics, &s.elem, with_ref_lifetime, generate_crate_ref); write!(w, "]").unwrap(); }, syn::Type::Tuple(s) => { write!(w, "(").unwrap(); for (idx, t) in s.elems.iter().enumerate() { if idx != 0 { write!(w, ", ").unwrap(); } - self.write_rust_type(w, generics, &t); + self.do_write_rust_type(w, generics, &t, with_ref_lifetime, generate_crate_ref); } write!(w, ")").unwrap(); }, _ => unimplemented!(), } } + pub fn write_rust_type(&self, w: &mut W, generics: Option<&GenericTypes>, t: &syn::Type, with_ref_lifetime: bool) { + self.do_write_rust_type(w, generics, t, with_ref_lifetime, false); + } + /// Prints a constructor for something which is "uninitialized" (but obviously not actually /// unint'd memory). @@ -2749,7 +2771,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { // lifetime, of which the only real available choice is `static`, obviously. write!(w, "&'static {}", crate_pfx).unwrap(); if !c_ty { - self.write_rust_path(w, generics, path); + self.write_rust_path(w, generics, path, with_ref_lifetime, false); } else { // We shouldn't be mapping references in types, so panic here unimplemented!();