/// Writes out a C++ wrapper class for the given type, which contains various utilities to access
/// the underlying C-mapped type safely avoiding some common memory management issues by handling
/// resource-freeing and prevending accidental raw copies.
-pub fn write_cpp_wrapper(cpp_header_file: &mut File, ty: &str, has_destructor: bool) {
+pub fn write_cpp_wrapper(cpp_header_file: &mut File, ty: &str, has_destructor: bool, trait_methods: Option<Vec<(String, String)>>) {
writeln!(cpp_header_file, "class {} {{", ty).unwrap();
writeln!(cpp_header_file, "private:").unwrap();
writeln!(cpp_header_file, "\tLDK{} self;", ty).unwrap();
writeln!(cpp_header_file, "\tLDK{}* operator ->() {{ return &self; }}", ty).unwrap();
writeln!(cpp_header_file, "\tconst LDK{}* operator &() const {{ return &self; }}", ty).unwrap();
writeln!(cpp_header_file, "\tconst LDK{}* operator ->() const {{ return &self; }}", ty).unwrap();
+ if let Some(methods) = trait_methods {
+ for (meth_name, meth_docs) in methods {
+ cpp_header_file.write_all(meth_docs.as_bytes()).unwrap();
+ // Note that we have zero logic to print C/C__ code for a given function. Instead, we
+ // simply use sed to replace the following in genbindings.sh
+ writeln!(cpp_header_file, "XXX {} {}", ty, meth_name).unwrap();
+ }
+ }
writeln!(cpp_header_file, "}};").unwrap();
}
writeln!(w, "\t}}").unwrap();
writeln!(w, "}}").unwrap();
- // TODO: Templates should use () now that they can, too
- let templ_ok_type = if ok_type != "()" { ok_type } else { "u8" };
- let templ_err_type = if err_type != "()" { err_type } else { "u8" };
-
- writeln!(w, "impl From<crate::c_types::CResultTempl<{}, {}>> for {} {{", templ_ok_type, templ_err_type, mangled_container).unwrap();
- writeln!(w, "\tfn from(mut o: crate::c_types::CResultTempl<{}, {}>) -> Self {{", templ_ok_type, templ_err_type).unwrap();
+ writeln!(w, "impl From<crate::c_types::CResultTempl<{}, {}>> for {} {{", ok_type, err_type, mangled_container).unwrap();
+ writeln!(w, "\tfn from(mut o: crate::c_types::CResultTempl<{}, {}>) -> Self {{", ok_type, err_type).unwrap();
writeln!(w, "\t\tlet contents = if o.result_ok {{").unwrap();
if ok_type != "()" {
writeln!(w, "\t\t\tlet result = unsafe {{ o.contents.result }};").unwrap();
for inp in sig.inputs.iter() {
match inp {
syn::FnArg::Receiver(recv) => {
- if !recv.attrs.is_empty() || recv.reference.is_none() { unimplemented!(); }
- write!(w, "this_arg: {}{}",
- match (self_ptr, recv.mutability.is_some()) {
- (true, true) => "*mut ",
- (true, false) => "*const ",
- (false, true) => "&mut ",
- (false, false) => "&",
- }, this_param).unwrap();
+ if !recv.attrs.is_empty() { unimplemented!(); }
+ write!(w, "{}this_arg: {}{}", if recv.reference.is_none() { "mut " } else { "" },
+ if recv.reference.is_some() {
+ match (self_ptr, recv.mutability.is_some()) {
+ (true, true) => "*mut ",
+ (true, false) => "*const ",
+ (false, true) => "&mut ",
+ (false, false) => "&",
+ }
+ } else { "" }, this_param).unwrap();
assert!(first_arg);
first_arg = false;
},
for inp in sig.inputs.iter() {
match inp {
syn::FnArg::Receiver(recv) => {
- if !recv.attrs.is_empty() || recv.reference.is_none() { unimplemented!(); }
+ if !recv.attrs.is_empty() { unimplemented!(); }
if to_c {
+ if recv.reference.is_none() { unimplemented!(); }
write!(w, "self.this_arg").unwrap();
first_arg = false;
}
/// Prints concrete generic parameters for a struct/trait/function, including the less-than and
/// greater-than symbols, if any generic parameters are defined.
pub fn maybe_write_generics<W: std::io::Write>(w: &mut W, generics: &syn::Generics, types: &TypeResolver, concrete_lifetimes: bool) {
- let mut gen_types = GenericTypes::new();
+ let mut gen_types = GenericTypes::new(None);
assert!(gen_types.learn_generics(generics, types));
if !generics.params.is_empty() {
write!(w, "<").unwrap();