Call methods explicitly on traits to avoid to deref recursion
[ldk-c-bindings] / c-bindings-gen / src / types.rs
index d17148fe25d1378d2ecec2d9c1f2a4f10394f8e5..efd6b9afcb24e48bbfef296dcb5e01984816a6b4 100644 (file)
@@ -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<syn::Type> {
+               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());
@@ -1875,7 +1922,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                                                DeclType::EnumIgnored|DeclType::StructImported if !is_ref =>
                                                        write!(w, "crate::{} {{ inner: ObjOps::heap_alloc(", decl_path).unwrap(),
                                                DeclType::Trait(_) if is_ref => write!(w, "").unwrap(),
-                                               DeclType::Trait(_) if !is_ref => {},
+                                               DeclType::Trait(_) if !is_ref => write!(w, "Into::into(").unwrap(),
                                                _ => panic!("{:?}", decl_path),
                                        }
                                });
@@ -1901,7 +1948,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                                                // for use when a Rust trait method returns an associated type.
                                                // Because all of our C traits implement From<RustTypesImplementingTraits>
                                                // we can just call .into() here and be done.
-                                               write!(w, ".into()").unwrap()
+                                               write!(w, ")").unwrap()
                                        },
                                        _ => unimplemented!(),
                                });
@@ -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();