X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=c-bindings-gen%2Fsrc%2Ftypes.rs;h=96a4135f9c1f3800a00a4eb7239d653a9cb95879;hb=97454869b647ffff5e0c37e5f6da19a7a33789a5;hp=d17148fe25d1378d2ecec2d9c1f2a4f10394f8e5;hpb=ed6eb46f7b4e0d4c869ad08dffc600b4e93e2129;p=ldk-c-bindings diff --git a/c-bindings-gen/src/types.rs b/c-bindings-gen/src/types.rs index d17148f..96a4135 100644 --- a/c-bindings-gen/src/types.rs +++ b/c-bindings-gen/src/types.rs @@ -1431,6 +1431,49 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { } } + /// Constructs a reference to the given type, possibly tweaking the type if relevant to make it + /// convertable to C. + pub fn create_ownable_reference(&self, t: &syn::Type, generics: Option<&GenericTypes>) -> Option { + let default_value = Some(syn::Type::Reference(syn::TypeReference { + and_token: syn::Token!(&)(Span::call_site()), lifetime: None, mutability: None, + elem: Box::new(t.clone()) })); + match t { + syn::Type::Path(p) => { + if let Some(resolved_path) = self.maybe_resolve_path(&p.path, generics) { + if resolved_path != "Vec" { return default_value; } + if p.path.segments.len() != 1 { unimplemented!(); } + let only_seg = p.path.segments.iter().next().unwrap(); + if let syn::PathArguments::AngleBracketed(args) = &only_seg.arguments { + if args.args.len() != 1 { unimplemented!(); } + let inner_arg = args.args.iter().next().unwrap(); + if let syn::GenericArgument::Type(ty) = &inner_arg { + let mut can_create = self.c_type_has_inner(&ty); + if let syn::Type::Path(inner) = ty { + if inner.path.segments.len() == 1 && + format!("{}", inner.path.segments[0].ident) == "Vec" { + can_create = true; + } + } + if !can_create { return default_value; } + if let Some(inner_ty) = self.create_ownable_reference(&ty, generics) { + return Some(syn::Type::Reference(syn::TypeReference { + and_token: syn::Token![&](Span::call_site()), + lifetime: None, + mutability: None, + elem: Box::new(syn::Type::Slice(syn::TypeSlice { + bracket_token: syn::token::Bracket { span: Span::call_site() }, + elem: Box::new(inner_ty) + })) + })); + } else { return default_value; } + } else { unimplemented!(); } + } else { unimplemented!(); } + } else { return None; } + }, + _ => default_value, + } + } + // ************************************************* // *** Type definition during main.rs processing *** // ************************************************* @@ -1442,12 +1485,14 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { pub fn c_type_has_inner_from_path(&self, full_path: &str) -> bool { self.crate_types.opaques.get(full_path).is_some() } + /// Returns true if the object at the given path is mapped as X { inner: *mut origX, .. }. pub fn c_type_has_inner(&self, ty: &syn::Type) -> bool { match ty { syn::Type::Path(p) => { - let full_path = self.resolve_path(&p.path, None); - self.c_type_has_inner_from_path(&full_path) + if let Some(full_path) = self.maybe_resolve_path(&p.path, None) { + self.c_type_has_inner_from_path(&full_path) + } else { false } }, syn::Type::Reference(r) => { self.c_type_has_inner(&*r.elem) @@ -1809,6 +1854,8 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { } else if let syn::Type::Reference(r) = &*s.elem { if let syn::Type::Path(p) = &*r.elem { write!(w, "{}", sliceconv(self.c_type_has_inner_from_path(&self.resolve_path(&p.path, generics)), None)).unwrap(); + } else if let syn::Type::Slice(_) = &*r.elem { + write!(w, "{}", sliceconv(false, None)).unwrap(); } else { unimplemented!(); } } else if let syn::Type::Tuple(t) = &*s.elem { assert!(!t.elems.is_empty()); @@ -2598,6 +2645,20 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { } else { return false; }; write!(w, "{}::{}", Self::generated_container_path(), mangled_container).unwrap(); self.check_create_container(mangled_container, "Vec", vec![&*r.elem], generics, false) + } else if let syn::Type::Slice(sl2) = &*r.elem { + if let syn::Type::Reference(r2) = &*sl2.elem { + if let syn::Type::Path(p) = &*r2.elem { + // Slices with slices with opaque types (with is_owned flags) are mapped as non-ref Vecs + let resolved = self.resolve_path(&p.path, generics); + let mangled_container = if let Some(ident) = self.crate_types.opaques.get(&resolved) { + format!("CVec_CVec_{}ZZ", ident) + } else { return false; }; + write!(w, "{}::{}", Self::generated_container_path(), mangled_container).unwrap(); + let inner = &r2.elem; + let vec_ty: syn::Type = syn::parse_quote!(Vec<#inner>); + self.check_create_container(mangled_container, "Vec", vec![&vec_ty], generics, false) + } else { false } + } else { false } } else { false } } else if let syn::Type::Tuple(_) = &*s.elem { let mut args = syn::punctuated::Punctuated::<_, syn::token::Comma>::new();