From: Matt Corallo Date: Tue, 5 Jan 2021 00:26:12 +0000 (-0500) Subject: [bindings] Move to manual write-out for Vec, too (XXX: with clone whitelist) X-Git-Url: http://git.bitcoin.ninja/?a=commitdiff_plain;h=daff17c8a1503063229338ce5edda1643ec00d7c;p=rust-lightning [bindings] Move to manual write-out for Vec, too (XXX: with clone whitelist) --- diff --git a/c-bindings-gen/src/blocks.rs b/c-bindings-gen/src/blocks.rs index 07482c4b4..01e6d1f70 100644 --- a/c-bindings-gen/src/blocks.rs +++ b/c-bindings-gen/src/blocks.rs @@ -146,6 +146,55 @@ pub fn write_result_block(w: &mut W, mangled_container: &str, writeln!(w, "}}").unwrap(); } +/// Writes out a C-callable concrete Vec struct and utility methods +pub fn write_vec_block(w: &mut W, mangled_container: &str, inner_type: &str) { + 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> 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 inner_type == "u8" || mangled_container == "CVec_SpendableOutputDescriptorZ" { // XXX + 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: &mut W, attrs: &[syn::Attribute], prefix: &str) { for attr in attrs.iter() { diff --git a/c-bindings-gen/src/types.rs b/c-bindings-gen/src/types.rs index 59cc51fef..4e420267f 100644 --- a/c-bindings-gen/src/types.rs +++ b/c-bindings-gen/src/types.rs @@ -1752,24 +1752,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| @@ -1847,6 +1837,10 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { } write_result_block(&mut created_container, &mangled_container, &String::from_utf8(a_ty).unwrap(), &String::from_utf8(b_ty).unwrap()); + } else if container_type == "Vec" { + let mut a_ty: Vec = Vec::new(); + self.write_template_generics(&mut a_ty, &mut args.iter().map(|t| *t), generics, is_ref, true); + write_vec_block(&mut created_container, &mangled_container, &String::from_utf8(a_ty).unwrap()); } else { write!(&mut created_container, "pub type {} = ", mangled_container).unwrap(); write!(&mut created_container, "{}::C{}Templ<", Self::container_templ_path(), container_type).unwrap(); diff --git a/lightning-c-bindings/src/c_types/mod.rs b/lightning-c-bindings/src/c_types/mod.rs index bc670947e..006f323f6 100644 --- a/lightning-c-bindings/src/c_types/mod.rs +++ b/lightning-c-bindings/src/c_types/mod.rs @@ -127,7 +127,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 }; } } } @@ -156,7 +156,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 } } @@ -220,7 +220,7 @@ impl lightning::util::ser::Writer for VecWriter { pub(crate) fn serialize_obj(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(s: u8slice) -> Result { I::read(&mut s.to_slice()) @@ -295,46 +295,6 @@ impl Drop for CResultTempl { } } -#[repr(C)] -pub struct CVecTempl { - pub data: *mut T, - pub datalen: usize -} -impl CVecTempl { - pub(crate) fn into_rust(&mut self) -> Vec { - 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 From> for CVecTempl { - fn from(v: Vec) -> 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(_res: CVecTempl) { } -impl Drop for CVecTempl { - fn drop(&mut self) { - if self.datalen == 0 { return; } - unsafe { Box::from_raw(std::slice::from_raw_parts_mut(self.data, self.datalen)) }; - } -} -impl Clone for CVecTempl { - 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 { pub a: A,