From: Matt Corallo Date: Wed, 3 Feb 2021 23:14:39 +0000 (-0500) Subject: [bindings] Move to manual write-out for Tuples, too X-Git-Tag: v0.0.13~32^2~5 X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=commitdiff_plain;h=faad5124cf74779ae386399dbf9954f47a79ca48;p=rust-lightning [bindings] Move to manual write-out for Tuples, too --- diff --git a/c-bindings-gen/src/blocks.rs b/c-bindings-gen/src/blocks.rs index 64cb163d..dd57a82b 100644 --- a/c-bindings-gen/src/blocks.rs +++ b/c-bindings-gen/src/blocks.rs @@ -221,6 +221,72 @@ pub fn write_vec_block(w: &mut W, mangled_container: &str, in } } +/// Writes out a C-callable concrete (A, B, ...) struct and utility methods +pub fn write_tuple_block(w: &mut W, mangled_container: &str, types: &[String], clonable: bool) { + writeln!(w, "#[repr(C)]").unwrap(); + writeln!(w, "pub struct {} {{", mangled_container).unwrap(); + for (idx, ty) in types.iter().enumerate() { + writeln!(w, "\tpub {}: {},", ('a' as u8 + idx as u8) as char, ty).unwrap(); + } + writeln!(w, "}}").unwrap(); + + let mut tuple_str = "(".to_owned(); + for (idx, ty) in types.iter().enumerate() { + if idx != 0 { tuple_str += ", "; } + tuple_str += ty; + } + tuple_str += ")"; + + writeln!(w, "impl From<{}> for {} {{", tuple_str, mangled_container).unwrap(); + writeln!(w, "\tfn from (tup: {}) -> Self {{", tuple_str).unwrap(); + writeln!(w, "\t\tSelf {{").unwrap(); + for idx in 0..types.len() { + writeln!(w, "\t\t\t{}: tup.{},", ('a' as u8 + idx as u8) as char, idx).unwrap(); + } + writeln!(w, "\t\t}}").unwrap(); + writeln!(w, "\t}}").unwrap(); + writeln!(w, "}}").unwrap(); + writeln!(w, "impl {} {{", mangled_container).unwrap(); + writeln!(w, "\t#[allow(unused)] pub(crate) fn to_rust(mut self) -> {} {{", tuple_str).unwrap(); + write!(w, "\t\t(").unwrap(); + for idx in 0..types.len() { + write!(w, "{}self.{}", if idx != 0 {", "} else {""}, ('a' as u8 + idx as u8) as char).unwrap(); + } + writeln!(w, ")").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\tSelf {{").unwrap(); + for idx in 0..types.len() { + writeln!(w, "\t\t\t{}: self.{}.clone(),", ('a' as u8 + idx as u8) as char, ('a' as u8 + idx as u8) as char).unwrap(); + } + writeln!(w, "\t\t}}").unwrap(); + writeln!(w, "\t}}").unwrap(); + writeln!(w, "}}").unwrap(); + writeln!(w, "#[no_mangle]").unwrap(); + writeln!(w, "pub extern \"C\" fn {}_clone(orig: &{}) -> {} {{ orig.clone() }}", mangled_container, mangled_container, mangled_container).unwrap(); + } + + write!(w, "#[no_mangle]\npub extern \"C\" fn {}_new(", mangled_container).unwrap(); + for (idx, gen) in types.iter().enumerate() { + write!(w, "{}{}: ", if idx != 0 { ", " } else { "" }, ('a' as u8 + idx as u8) as char).unwrap(); + //if !self.write_c_type_intern(&mut created_container, gen, generics, false, false, false) { return false; } + write!(w, "{}", gen).unwrap(); + } + writeln!(w, ") -> {} {{", mangled_container).unwrap(); + write!(w, "\t{} {{ ", mangled_container).unwrap(); + for idx in 0..types.len() { + write!(w, "{}, ", ('a' as u8 + idx as u8) as char).unwrap(); + } + writeln!(w, "}}\n}}\n").unwrap(); + + writeln!(w, "#[no_mangle]").unwrap(); + writeln!(w, "pub extern \"C\" fn {}_free(_res: {}) {{ }}", mangled_container, mangled_container).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 ab85f7b4..7205c9f6 100644 --- a/c-bindings-gen/src/types.rs +++ b/c-bindings-gen/src/types.rs @@ -1786,9 +1786,11 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { if tup.elems.is_empty() { write!(w, "u8").unwrap(); } else { - write!(w, "{}::C{}TupleTempl<", Self::container_templ_path(), tup.elems.len()).unwrap(); - self.write_template_generics(w, &mut tup.elems.iter(), generics, is_ref, in_crate); - write!(w, ">").unwrap(); + let mut inner_args = Vec::new(); + for arg in tup.elems.iter() { + inner_args.push(arg); + } + assert!(self.write_c_mangled_container_path(w, inner_args, generics, &format!("{}Tuple", tup.elems.len()), is_ref, false, false)); } } else if let syn::Type::Path(p_arg) = t { let resolved_generic = self.resolve_path(&p_arg.path, generics); @@ -1896,20 +1898,24 @@ 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 { - write!(&mut created_container, "pub type {} = ", mangled_container).unwrap(); - write!(&mut created_container, "{}::C{}Templ<", Self::container_templ_path(), container_type).unwrap(); - self.write_template_generics(&mut created_container, &mut args.iter().map(|t| *t), generics, is_ref, true); - writeln!(&mut created_container, ">;").unwrap(); - - write!(&mut created_container, "#[no_mangle]\npub static {}_free: extern \"C\" fn({}) = ", mangled_container, mangled_container).unwrap(); - write!(&mut created_container, "{}::C{}Templ_free::<", Self::container_templ_path(), container_type).unwrap(); - self.write_template_generics(&mut created_container, &mut args.iter().map(|t| *t), generics, is_ref, true); - writeln!(&mut created_container, ">;").unwrap(); - - if !self.write_template_constructor(&mut created_container, container_type, &mangled_container, &args, generics, is_ref) { - return false; + } else if container_type.ends_with("Tuple") { + let mut tuple_args = Vec::new(); + let mut is_clonable = true; + for arg in args.iter() { + let mut ty: Vec = Vec::new(); + self.write_template_generics(&mut ty, &mut [arg].iter().map(|t| **t), generics, is_ref, true); + let ty_str = String::from_utf8(ty).unwrap(); + if !self.is_clonable(&ty_str) { + is_clonable = false; + } + tuple_args.push(ty_str); } + write_tuple_block(&mut created_container, &mangled_container, &tuple_args, is_clonable); + if is_clonable { + self.crate_types.clonable_types.insert(Self::generated_container_path().to_owned() + "::" + &mangled_container); + } + } else { + unreachable!(); } self.crate_types.templates_defined.insert(mangled_container.clone(), true); @@ -2008,7 +2014,6 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { } else if let syn::Type::Path(p_arg) = arg { write_path!(p_arg, None); } else if let syn::Type::Reference(refty) = arg { - if args.len() != 1 { return false; } if let syn::Type::Path(p_arg) = &*refty.elem { write_path!(p_arg, None); } else if let syn::Type::Slice(_) = &*refty.elem { @@ -2016,6 +2021,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { // make it a pointer so that its an option. Note that we cannot always convert // the Vec-as-slice (ie non-ref types) containers, so sometimes need to be able // to edit it, hence we use *mut here instead of *const. + if args.len() != 1 { return false; } write!(w, "*mut ").unwrap(); self.write_c_type(w, arg, None, true); } else { return false; } diff --git a/lightning-c-bindings/src/c_types/mod.rs b/lightning-c-bindings/src/c_types/mod.rs index 76807621..074aef25 100644 --- a/lightning-c-bindings/src/c_types/mod.rs +++ b/lightning-c-bindings/src/c_types/mod.rs @@ -298,56 +298,6 @@ impl Drop for CResultTempl { } } -#[repr(C)] -pub struct C2TupleTempl { - pub a: A, - pub b: B, -} -impl From<(A, B)> for C2TupleTempl { - fn from(tup: (A, B)) -> Self { - Self { - a: tup.0, - b: tup.1, - } - } -} -impl C2TupleTempl { - pub(crate) fn to_rust(mut self) -> (A, B) { - (self.a, self.b) - } -} -pub extern "C" fn C2TupleTempl_free(_res: C2TupleTempl) { } -impl Clone for C2TupleTempl { - fn clone(&self) -> Self { - Self { - a: self.a.clone(), - b: self.b.clone() - } - } -} - -#[repr(C)] -pub struct C3TupleTempl { - pub a: A, - pub b: B, - pub c: C, -} -impl From<(A, B, C)> for C3TupleTempl { - fn from(tup: (A, B, C)) -> Self { - Self { - a: tup.0, - b: tup.1, - c: tup.2, - } - } -} -impl C3TupleTempl { - pub(crate) fn to_rust(mut self) -> (A, B, C) { - (self.a, self.b, self.c) - } -} -pub extern "C" fn C3TupleTempl_free(_res: C3TupleTempl) { } - /// Utility to make it easy to set a pointer to null and get its original value in line. pub(crate) trait TakePointer { fn take_ptr(&mut self) -> T;