X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=c-bindings-gen%2Fsrc%2Ftypes.rs;h=6e10bd6068920a4119083f2ce9b468e98fb9b10c;hb=83bfbaac7e34688fda82d4b2dc8fb94967c394be;hp=1e1bffa34b85e4fa52756d6abcd9d80936299030;hpb=c9012b42c733d6acb43fae6be4c3c212f26d0c69;p=ldk-c-bindings diff --git a/c-bindings-gen/src/types.rs b/c-bindings-gen/src/types.rs index 1e1bffa..6e10bd6 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))); } }, _ => {}, @@ -268,7 +273,8 @@ impl<'a, 'p: 'a> GenericTypes<'a, 'p> { if p.qself.is_some() { return false; } if p.path.leading_colon.is_some() { return false; } let mut p_iter = p.path.segments.iter(); - if let Some(gen) = new_typed_generics.get_mut(&p_iter.next().unwrap().ident) { + let p_ident = &p_iter.next().unwrap().ident; + if let Some(gen) = new_typed_generics.get_mut(p_ident) { if gen.is_some() { return false; } if &format!("{}", p_iter.next().unwrap().ident) != "Target" {return false; } @@ -281,7 +287,15 @@ impl<'a, 'p: 'a> GenericTypes<'a, 'p> { if non_lifetimes_processed { return false; } non_lifetimes_processed = true; assert_simple_bound(&trait_bound); - *gen = Some(types.resolve_path(&trait_bound.path, None)); + let resolved = types.resolve_path(&trait_bound.path, None); + let ty = syn::Type::Path(syn::TypePath { + qself: None, path: string_path_to_syn_path(&resolved) + }); + let ref_ty = parse_quote!(&#ty); + let mut_ref_ty = parse_quote!(&mut #ty); + self.default_generics.insert(p_ident, (ty, ref_ty, mut_ref_ty)); + + *gen = Some(resolved); } } } else { return false; } @@ -370,16 +384,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); + } } } } @@ -438,6 +456,10 @@ impl<'mod_lifetime, 'crate_lft: 'mod_lifetime> ImportResolver<'mod_lifetime, 'cr new_path = format!("{}::{}{}", crate_name, $ident, $path_suffix); let crate_name_ident = format_ident!("{}", crate_name); path.push(parse_quote!(#crate_name_ident)); + } else if format!("{}", $ident) == "self" { + let mut path_iter = partial_path.rsplitn(2, "::"); + path_iter.next().unwrap(); + new_path = path_iter.next().unwrap().to_owned(); } else { new_path = format!("{}{}{}", partial_path, $ident, $path_suffix); } @@ -452,7 +474,8 @@ impl<'mod_lifetime, 'crate_lft: 'mod_lifetime> ImportResolver<'mod_lifetime, 'cr }, syn::UseTree::Name(n) => { push_path!(n.ident, ""); - imports.insert(n.ident.clone(), (new_path, syn::Path { leading_colon: Some(syn::Token![::](Span::call_site())), segments: path })); + let imported_ident = syn::Ident::new(new_path.rsplitn(2, "::").next().unwrap(), Span::call_site()); + imports.insert(imported_ident, (new_path, syn::Path { leading_colon: Some(syn::Token![::](Span::call_site())), segments: path })); }, syn::UseTree::Group(g) => { for i in g.items.iter() { @@ -711,6 +734,10 @@ impl FullLibraryAST { fn initial_clonable_types() -> HashSet { let mut res = HashSet::new(); res.insert("crate::c_types::u5".to_owned()); + res.insert("crate::c_types::FourBytes".to_owned()); + res.insert("crate::c_types::TwelveBytes".to_owned()); + res.insert("crate::c_types::SixteenBytes".to_owned()); + res.insert("crate::c_types::TwentyBytes".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()); @@ -718,8 +745,17 @@ fn initial_clonable_types() -> HashSet { res.insert("crate::c_types::TxOut".to_owned()); res.insert("crate::c_types::Signature".to_owned()); res.insert("crate::c_types::RecoverableSignature".to_owned()); + res.insert("crate::c_types::Bech32Error".to_owned()); res.insert("crate::c_types::Secp256k1Error".to_owned()); res.insert("crate::c_types::IOError".to_owned()); + res.insert("crate::c_types::Error".to_owned()); + res.insert("crate::c_types::Str".to_owned()); + + // Because some types are manually-mapped to CVec_u8Z we may end up checking if its clonable + // before we ever get to constructing the type fully via + // `write_c_mangled_container_path_intern` (which will add it here too), so we have to manually + // add it on startup. + res.insert("crate::c_types::derived::CVec_u8Z".to_owned()); res } @@ -1490,7 +1526,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { if let Some(t) = single_contained { match t { - syn::Type::Reference(_)|syn::Type::Path(_)|syn::Type::Slice(_) => { + syn::Type::Reference(_)|syn::Type::Path(_)|syn::Type::Slice(_)|syn::Type::Array(_) => { let mut v = Vec::new(); let ret_ref = self.write_empty_rust_val_check_suffix(generics, &mut v, t); let s = String::from_utf8(v).unwrap(); @@ -1786,7 +1822,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) { - write!(w, ".data").unwrap(); return self.write_empty_rust_val_check_suffix(generics, w, &arr_ty); } if self.crate_types.opaques.get(&resolved).is_some() { @@ -1806,7 +1841,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { syn::Type::Array(a) => { if let syn::Expr::Lit(l) = &a.len { if let syn::Lit::Int(i) = &l.lit { - write!(w, " == [0; {}]", i.base10_digits()).unwrap(); + write!(w, ".data == [0; {}]", i.base10_digits()).unwrap(); EmptyValExpectedTy::NonPointer } else { unimplemented!(); } } else { unimplemented!(); }