[bindings] Move to manual write-out for Vec, too
authorMatt Corallo <git@bluematt.me>
Tue, 5 Jan 2021 00:26:12 +0000 (19:26 -0500)
committerMatt Corallo <git@bluematt.me>
Thu, 11 Feb 2021 03:25:10 +0000 (22:25 -0500)
c-bindings-gen/src/blocks.rs
c-bindings-gen/src/types.rs
lightning-c-bindings/src/c_types/mod.rs

index 9ae0dab2ecc6cd8eb3f36e9afcaf305dc9a289b2..64cb163d7c87add810f290f7e776852cc1861938 100644 (file)
@@ -172,6 +172,55 @@ pub fn write_result_block<W: std::io::Write>(w: &mut W, mangled_container: &str,
        }
 }
 
+/// Writes out a C-callable concrete Vec<A> struct and utility methods
+pub fn write_vec_block<W: std::io::Write>(w: &mut W, mangled_container: &str, inner_type: &str, clonable: bool) {
+       writeln!(w, "#[repr(C)]").unwrap();
+       writeln!(w, "pub struct {} {{", mangled_container).unwrap();
+       writeln!(w, "\tpub data: *mut {},", inner_type).unwrap();
+       writeln!(w, "\tpub datalen: usize").unwrap();
+       writeln!(w, "}}").unwrap();
+
+       writeln!(w, "impl {} {{", mangled_container).unwrap();
+       writeln!(w, "\t#[allow(unused)] pub(crate) fn into_rust(&mut self) -> Vec<{}> {{", inner_type).unwrap();
+       writeln!(w, "\t\tif self.datalen == 0 {{ return Vec::new(); }}").unwrap();
+       writeln!(w, "\t\tlet ret = unsafe {{ Box::from_raw(std::slice::from_raw_parts_mut(self.data, self.datalen)) }}.into();").unwrap();
+       writeln!(w, "\t\tself.data = std::ptr::null_mut();").unwrap();
+       writeln!(w, "\t\tself.datalen = 0;").unwrap();
+       writeln!(w, "\t\tret").unwrap();
+       writeln!(w, "\t}}").unwrap();
+       writeln!(w, "\t#[allow(unused)] pub(crate) fn as_slice(&self) -> &[{}] {{", inner_type).unwrap();
+       writeln!(w, "\t\tunsafe {{ std::slice::from_raw_parts_mut(self.data, self.datalen) }}").unwrap();
+       writeln!(w, "\t}}").unwrap();
+       writeln!(w, "}}").unwrap();
+
+       writeln!(w, "impl From<Vec<{}>> for {} {{", inner_type, mangled_container).unwrap();
+       writeln!(w, "\tfn from(v: Vec<{}>) -> Self {{", inner_type).unwrap();
+       writeln!(w, "\t\tlet datalen = v.len();").unwrap();
+       writeln!(w, "\t\tlet data = Box::into_raw(v.into_boxed_slice());").unwrap();
+       writeln!(w, "\t\tSelf {{ datalen, data: unsafe {{ (*data).as_mut_ptr() }} }}").unwrap();
+       writeln!(w, "\t}}").unwrap();
+       writeln!(w, "}}").unwrap();
+
+       writeln!(w, "#[no_mangle]").unwrap();
+       writeln!(w, "pub extern \"C\" fn {}_free(_res: {}) {{ }}", mangled_container, mangled_container).unwrap();
+       writeln!(w, "impl Drop for {} {{", mangled_container).unwrap();
+       writeln!(w, "\tfn drop(&mut self) {{").unwrap();
+       writeln!(w, "\t\tif self.datalen == 0 {{ return; }}").unwrap();
+       writeln!(w, "\t\tunsafe {{ Box::from_raw(std::slice::from_raw_parts_mut(self.data, self.datalen)) }};").unwrap();
+       writeln!(w, "\t}}").unwrap();
+       writeln!(w, "}}").unwrap();
+       if clonable {
+               writeln!(w, "impl Clone for {} {{", mangled_container).unwrap();
+               writeln!(w, "\tfn clone(&self) -> Self {{").unwrap();
+               writeln!(w, "\t\tlet mut res = Vec::new();").unwrap();
+               writeln!(w, "\t\tif self.datalen == 0 {{ return Self::from(res); }}").unwrap();
+               writeln!(w, "\t\tres.extend_from_slice(unsafe {{ std::slice::from_raw_parts_mut(self.data, self.datalen) }});").unwrap();
+               writeln!(w, "\t\tSelf::from(res)").unwrap();
+               writeln!(w, "\t}}").unwrap();
+               writeln!(w, "}}").unwrap();
+       }
+}
+
 /// Prints the docs from a given attribute list unless its tagged no export
 pub fn writeln_docs<W: std::io::Write>(w: &mut W, attrs: &[syn::Attribute], prefix: &str) {
        for attr in attrs.iter() {
index 7e781a03e2c500b0227e23138f4ba09a9e20222d..ab85f7b424868c59b158bf5bfe1469f5732df075 100644 (file)
@@ -1796,24 +1796,14 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                                        write!(w, "{}", resolved_generic).unwrap();
                                } else if let Some(c_type) = self.c_type_from_path(&resolved_generic, is_ref, false) {
                                        if self.is_known_container(&resolved_generic, is_ref) {
-                                               if resolved_generic == "Result" {
-                                                       let mut inner_args = Vec::new();
-                                                       if let syn::PathArguments::AngleBracketed(args) = &p_arg.path.segments.iter().next().unwrap().arguments {
-                                                               for arg in args.args.iter() {
-                                                                       if let syn::GenericArgument::Type(t) = arg { inner_args.push(t) } else { unimplemented!() };
-                                                               }
-                                                       } else { unimplemented!(); }
-                                                       self.write_c_mangled_container_path(w, inner_args, generics, &resolved_generic, is_ref, false, false);
-                                               } else {
-                                                       write!(w, "{}::C{}Templ<", Self::container_templ_path(), single_ident_generic_path_to_ident(&p_arg.path).unwrap()).unwrap();
-                                                       assert_eq!(p_arg.path.segments.len(), 1);
-                                                       if let syn::PathArguments::AngleBracketed(args) = &p_arg.path.segments.iter().next().unwrap().arguments {
-                                                               self.write_template_generics(w, &mut args.args.iter().map(|gen|
-                                                                       if let syn::GenericArgument::Type(t) = gen { t } else { unimplemented!() }),
-                                                                       generics, is_ref, in_crate);
-                                                       } else { unimplemented!(); }
-                                                       write!(w, ">").unwrap();
-                                               }
+                                               assert!(resolved_generic == "Vec" || resolved_generic == "Result");
+                                               let mut inner_args = Vec::new();
+                                               if let syn::PathArguments::AngleBracketed(args) = &p_arg.path.segments.iter().next().unwrap().arguments {
+                                                       for arg in args.args.iter() {
+                                                               if let syn::GenericArgument::Type(t) = arg { inner_args.push(t) } else { unimplemented!() };
+                                                       }
+                                               } else { unimplemented!(); }
+                                               assert!(self.write_c_mangled_container_path(w, inner_args, generics, &resolved_generic, is_ref, false, false));
                                        } else if resolved_generic == "Option" {
                                                if let syn::PathArguments::AngleBracketed(args) = &p_arg.path.segments.iter().next().unwrap().arguments {
                                                        self.write_template_generics(w, &mut args.args.iter().map(|gen|
@@ -1897,6 +1887,15 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                                if is_clonable {
                                        self.crate_types.clonable_types.insert(Self::generated_container_path().to_owned() + "::" + &mangled_container);
                                }
+                       } else if container_type == "Vec" {
+                               let mut a_ty: Vec<u8> = Vec::new();
+                               self.write_template_generics(&mut a_ty, &mut args.iter().map(|t| *t), generics, is_ref, true);
+                               let ty = String::from_utf8(a_ty).unwrap();
+                               let is_clonable = self.is_clonable(&ty);
+                               write_vec_block(&mut created_container, &mangled_container, &ty, is_clonable);
+                               if is_clonable {
+                                       self.crate_types.clonable_types.insert(Self::generated_container_path().to_owned() + "::" + &mangled_container);
+                               }
                        } else {
                                write!(&mut created_container, "pub type {} = ", mangled_container).unwrap();
                                write!(&mut created_container, "{}::C{}Templ<", Self::container_templ_path(), container_type).unwrap();
index 5f8eb258aa93502bcdc097550e0af2f1e6952fa4..76807621c2681943c5bcc4712531528b45d9cff3 100644 (file)
@@ -128,7 +128,7 @@ impl Transaction {
 impl Drop for Transaction {
        fn drop(&mut self) {
                if self.data_is_owned && self.datalen != 0 {
-                       let _ = CVecTempl { data: self.data as *mut u8, datalen: self.datalen };
+                       let _ = derived::CVec_u8Z { data: self.data as *mut u8, datalen: self.datalen };
                }
        }
 }
@@ -157,7 +157,7 @@ impl TxOut {
        }
        pub(crate) fn from_rust(txout: ::bitcoin::blockdata::transaction::TxOut) -> Self {
                Self {
-                       script_pubkey: CVecTempl::from(txout.script_pubkey.into_bytes()),
+                       script_pubkey: derived::CVec_u8Z::from(txout.script_pubkey.into_bytes()),
                        value: txout.value
                }
        }
@@ -223,7 +223,7 @@ impl lightning::util::ser::Writer for VecWriter {
 pub(crate) fn serialize_obj<I: lightning::util::ser::Writeable>(i: &I) -> derived::CVec_u8Z {
        let mut out = VecWriter(Vec::new());
        i.write(&mut out).unwrap();
-       CVecTempl::from(out.0)
+       derived::CVec_u8Z::from(out.0)
 }
 pub(crate) fn deserialize_obj<I: lightning::util::ser::Readable>(s: u8slice) -> Result<I, lightning::ln::msgs::DecodeError> {
        I::read(&mut s.to_slice())
@@ -298,46 +298,6 @@ impl<O, E> Drop for CResultTempl<O, E> {
        }
 }
 
-#[repr(C)]
-pub struct CVecTempl<T> {
-       pub data: *mut T,
-       pub datalen: usize
-}
-impl<T> CVecTempl<T> {
-       pub(crate) fn into_rust(&mut self) -> Vec<T> {
-               if self.datalen == 0 { return Vec::new(); }
-               let ret = unsafe { Box::from_raw(std::slice::from_raw_parts_mut(self.data, self.datalen)) }.into();
-               self.data = std::ptr::null_mut();
-               self.datalen = 0;
-               ret
-       }
-       pub(crate) fn as_slice(&self) -> &[T] {
-               unsafe { std::slice::from_raw_parts_mut(self.data, self.datalen) }
-       }
-}
-impl<T> From<Vec<T>> for CVecTempl<T> {
-       fn from(v: Vec<T>) -> Self {
-               let datalen = v.len();
-               let data = Box::into_raw(v.into_boxed_slice());
-               CVecTempl { datalen, data: unsafe { (*data).as_mut_ptr() } }
-       }
-}
-pub extern "C" fn CVecTempl_free<T>(_res: CVecTempl<T>) { }
-impl<T> Drop for CVecTempl<T> {
-       fn drop(&mut self) {
-               if self.datalen == 0 { return; }
-               unsafe { Box::from_raw(std::slice::from_raw_parts_mut(self.data, self.datalen)) };
-       }
-}
-impl<T: Clone> Clone for CVecTempl<T> {
-       fn clone(&self) -> Self {
-               let mut res = Vec::new();
-               if self.datalen == 0 { return Self::from(res); }
-               res.extend_from_slice(unsafe { std::slice::from_raw_parts_mut(self.data, self.datalen) });
-               Self::from(res)
-       }
-}
-
 #[repr(C)]
 pub struct C2TupleTempl<A, B> {
        pub a: A,