[bindings] Use global context for secp256k1
[rust-lightning] / c-bindings-gen / src / types.rs
index afe719ffe2ca11709f50f6942dbf629fc9920084..7fc7e4cd905cff8d1cc66cd39aba44988b38c535 100644 (file)
@@ -114,16 +114,20 @@ pub fn assert_simple_bound(bound: &syn::TraitBound) {
 /// type), otherwise it is mapped into a transparent, C-compatible version of itself.
 pub fn is_enum_opaque(e: &syn::ItemEnum) -> bool {
        for var in e.variants.iter() {
-               if let syn::Fields::Unit = var.fields {
-               } else if let syn::Fields::Named(fields) = &var.fields {
+               if let syn::Fields::Named(fields) = &var.fields {
                        for field in fields.named.iter() {
                                match export_status(&field.attrs) {
                                        ExportStatus::Export|ExportStatus::TestOnly => {},
                                        ExportStatus::NoExport => return true,
                                }
                        }
-               } else {
-                       return true;
+               } else if let syn::Fields::Unnamed(fields) = &var.fields {
+                       for field in fields.unnamed.iter() {
+                               match export_status(&field.attrs) {
+                                       ExportStatus::Export|ExportStatus::TestOnly => {},
+                                       ExportStatus::NoExport => return true,
+                               }
+                       }
                }
        }
        false
@@ -383,6 +387,21 @@ 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 {
+                                                       match &*t.ty {
+                                                               syn::Type::Path(_) => { declared.insert(t.ident.clone(), DeclType::StructImported); },
+                                                               _ => {},
+                                                       }
+                                               }
+                                       }
+                               },
                                syn::Item::Enum(e) => {
                                        if let syn::Visibility::Public(_) = e.vis {
                                                match export_status(&e.attrs) {
@@ -514,6 +533,8 @@ pub struct CrateTypes<'a> {
        pub traits: HashMap<String, &'a syn::ItemTrait>,
        /// Aliases from paths to some other Type
        pub type_aliases: HashMap<String, syn::Type>,
+       /// Value is an alias to Key (maybe with some generics)
+       pub reverse_alias_map: HashMap<String, Vec<(syn::Path, syn::PathArguments)>>,
        /// Template continer types defined, map from mangled type name -> whether a destructor fn
        /// exists.
        ///
@@ -524,6 +545,8 @@ pub struct CrateTypes<'a> {
        pub template_file: &'a mut File,
        /// Set of containers which are clonable
        pub clonable_types: HashSet<String>,
+       /// Key impls Value
+       pub trait_impls: HashMap<String, Vec<String>>,
 }
 
 /// A struct which tracks resolving rust types into C-mapped equivalents, exists for one specific
@@ -564,7 +587,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
        /// Returns true we if can just skip passing this to C entirely
        fn no_arg_path_to_rust(&self, full_path: &str) -> &str {
                if full_path == "bitcoin::secp256k1::Secp256k1" {
-                       "&bitcoin::secp256k1::Secp256k1::new()"
+                       "secp256k1::SECP256K1"
                } else { unimplemented!(); }
        }
 
@@ -593,7 +616,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
        }
        /// Gets the C-mapped type for types which are outside of the crate, or which are manually
        /// ignored by for some reason need mapping anyway.
-       fn c_type_from_path<'b>(&self, full_path: &'b str, is_ref: bool, ptr_for_ref: bool) -> Option<&'b str> {
+       fn c_type_from_path<'b>(&self, full_path: &'b str, is_ref: bool, _ptr_for_ref: bool) -> Option<&'b str> {
                if self.is_primitive(full_path) {
                        return Some(full_path);
                }
@@ -647,10 +670,6 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                        // Override the default since Records contain an fmt with a lifetime:
                        "util::logger::Record" => Some("*const std::os::raw::c_char"),
 
-                       // List of structs we map that aren't detected:
-                       "ln::features::InitFeatures" if is_ref && ptr_for_ref => Some("crate::ln::features::InitFeatures"),
-                       "ln::features::InitFeatures" if is_ref => Some("*const crate::ln::features::InitFeatures"),
-                       "ln::features::InitFeatures" => Some("crate::ln::features::InitFeatures"),
                        _ => None,
                }
        }
@@ -710,9 +729,6 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                        "ln::channelmanager::PaymentPreimage" if is_ref => Some("&::lightning::ln::channelmanager::PaymentPreimage(unsafe { *"),
                        "ln::channelmanager::PaymentSecret" => Some("::lightning::ln::channelmanager::PaymentSecret("),
 
-                       // List of structs we map (possibly during processing of other files):
-                       "ln::features::InitFeatures" if !is_ref => Some("*unsafe { Box::from_raw("),
-
                        // List of traits we map (possibly during processing of other files):
                        "crate::util::logger::Logger" => Some(""),
 
@@ -765,10 +781,6 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                        "ln::channelmanager::PaymentPreimage" if is_ref => Some(" })"),
                        "ln::channelmanager::PaymentSecret" => Some(".data)"),
 
-                       // List of structs we map (possibly during processing of other files):
-                       "ln::features::InitFeatures" if is_ref => Some(".inner) }"),
-                       "ln::features::InitFeatures" if !is_ref => Some(".take_inner()) }"),
-
                        // List of traits we map (possibly during processing of other files):
                        "crate::util::logger::Logger" => Some(""),
 
@@ -796,7 +808,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                        _ => None,
                }.map(|s| s.to_owned())
        }
-       fn to_c_conversion_inline_prefix_from_path(&self, full_path: &str, is_ref: bool, ptr_for_ref: bool) -> Option<String> {
+       fn to_c_conversion_inline_prefix_from_path(&self, full_path: &str, is_ref: bool, _ptr_for_ref: bool) -> Option<String> {
                if self.is_primitive(full_path) {
                        return Some("".to_owned());
                }
@@ -849,15 +861,10 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                        // Override the default since Records contain an fmt with a lifetime:
                        "util::logger::Record" => Some("local_"),
 
-                       // List of structs we map (possibly during processing of other files):
-                       "ln::features::InitFeatures" if is_ref && ptr_for_ref => Some("crate::ln::features::InitFeatures { inner: &mut "),
-                       "ln::features::InitFeatures" if is_ref => Some("Box::into_raw(Box::new(crate::ln::features::InitFeatures { inner: &mut "),
-                       "ln::features::InitFeatures" if !is_ref => Some("crate::ln::features::InitFeatures { inner: Box::into_raw(Box::new("),
-
                        _ => None,
                }.map(|s| s.to_owned())
        }
-       fn to_c_conversion_inline_suffix_from_path(&self, full_path: &str, is_ref: bool, ptr_for_ref: bool) -> Option<String> {
+       fn to_c_conversion_inline_suffix_from_path(&self, full_path: &str, is_ref: bool, _ptr_for_ref: bool) -> Option<String> {
                if self.is_primitive(full_path) {
                        return Some("".to_owned());
                }
@@ -911,11 +918,6 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                        // Override the default since Records contain an fmt with a lifetime:
                        "util::logger::Record" => Some(".as_ptr()"),
 
-                       // List of structs we map (possibly during processing of other files):
-                       "ln::features::InitFeatures" if is_ref && ptr_for_ref => Some(", is_owned: false }"),
-                       "ln::features::InitFeatures" if is_ref => Some(", is_owned: false }))"),
-                       "ln::features::InitFeatures" => Some(")), is_owned: true }"),
-
                        _ => None,
                }.map(|s| s.to_owned())
        }
@@ -965,7 +967,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                                                ").into() }"))
                        },
                        "Vec" if !is_ref => {
-                               Some(("Vec::new(); for item in ", vec![(format!(".drain(..) {{ local_{}.push(", var_name), "item".to_string())], "); }"))
+                               Some(("Vec::new(); for mut item in ", vec![(format!(".drain(..) {{ local_{}.push(", var_name), "item".to_string())], "); }"))
                        },
                        "Slice" => {
                                Some(("Vec::new(); for item in ", vec![(format!(".iter() {{ local_{}.push(", var_name), "**item".to_string())], "); }"))
@@ -1006,8 +1008,8 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                match full_path {
                        "Result" if !is_ref => {
                                Some(("match ",
-                                               vec![(".result_ok { true => Ok(".to_string(), format!("(*unsafe {{ Box::from_raw(<*mut _>::take_ptr(&mut {}.contents.result)) }})", var_name)),
-                                                    ("), false => Err(".to_string(), format!("(*unsafe {{ Box::from_raw(<*mut _>::take_ptr(&mut {}.contents.err)) }})", var_name))],
+                                               vec![(".result_ok { true => Ok(".to_string(), format!("(*unsafe {{ Box::from_raw(<*mut _>::take_ptr(&mut {}.contents.result)) }})", var_access)),
+                                                    ("), false => Err(".to_string(), format!("(*unsafe {{ Box::from_raw(<*mut _>::take_ptr(&mut {}.contents.err)) }})", var_access))],
                                                ")}"))
                        },
                        "Vec"|"Slice" if !is_ref => {
@@ -1020,9 +1022,9 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                                if let Some(syn::Type::Path(p)) = single_contained {
                                        if self.c_type_has_inner_from_path(&self.resolve_path(&p.path, generics)) {
                                                if is_ref {
-                                                       return Some(("if ", vec![(".inner.is_null() { None } else { Some((*".to_string(), format!("{}", var_name))], ").clone()) }"))
+                                                       return Some(("if ", vec![(".inner.is_null() { None } else { Some((*".to_string(), format!("{}", var_access))], ").clone()) }"))
                                                } else {
-                                                       return Some(("if ", vec![(".inner.is_null() { None } else { Some(".to_string(), format!("{}", var_name))], ") }"));
+                                                       return Some(("if ", vec![(".inner.is_null() { None } else { Some(".to_string(), format!("{}", var_access))], ") }"));
                                                }
                                        }
                                }