Merge pull request #19 from TheBlueMatt/2021-04-invoice-incl
[ldk-c-bindings] / c-bindings-gen / src / main.rs
index 918a05a935e0c117d93f3dddfcb92365a178a78a..c2ef30fbcf83a9e0c37204e1ee1b0f9466756ba4 100644 (file)
@@ -388,7 +388,7 @@ fn writeln_trait<'a, 'b, W: std::io::Write>(w: &mut W, t: &'a syn::ItemTrait, ty
                                                                                                        ident.mutability.is_some() || ident.subpat.is_some() {
                                                                                                unimplemented!();
                                                                                        }
-                                                                                       write!(w, ", {}{}: ", if $type_resolver.skip_arg(&*arg.ty, Some(&meth_gen_types)) { "_" } else { "" }, ident.ident).unwrap();
+                                                                                       write!(w, ", mut {}{}: ", if $type_resolver.skip_arg(&*arg.ty, Some(&meth_gen_types)) { "_" } else { "" }, ident.ident).unwrap();
                                                                                }
                                                                                _ => unimplemented!(),
                                                                        }
@@ -966,7 +966,7 @@ fn writeln_impl<W: std::io::Write>(w: &mut W, i: &syn::ItemImpl, types: &mut Typ
                                                        writeln!(w, "#[no_mangle]").unwrap();
                                                        writeln!(w, "/// Read a {} object from a string", ident).unwrap();
                                                        writeln!(w, "pub extern \"C\" fn {}_from_str(s: crate::c_types::Str) -> {} {{", ident, container).unwrap();
-                                                       writeln!(w, "\tmatch {}::from_str(s.into()) {{", resolved_path).unwrap();
+                                                       writeln!(w, "\tmatch {}::from_str(s.into_str()) {{", resolved_path).unwrap();
                                                        writeln!(w, "\t\tOk(r) => {{").unwrap();
                                                        let new_var = types.write_to_c_conversion_new_var(w, &format_ident!("r"), &*i.self_ty, Some(&gen_types), false);
                                                        write!(w, "\t\t\tcrate::c_types::CResultTempl::ok(\n\t\t\t\t").unwrap();
@@ -974,7 +974,7 @@ fn writeln_impl<W: std::io::Write>(w: &mut W, i: &syn::ItemImpl, types: &mut Typ
                                                        write!(w, "{}r", if new_var { "local_" } else { "" }).unwrap();
                                                        types.write_to_c_conversion_inline_suffix(w, &*i.self_ty, Some(&gen_types), false);
                                                        writeln!(w, "\n\t\t\t)\n\t\t}},").unwrap();
-                                                       writeln!(w, "\t\tErr(e) => crate::c_types::CResultTempl::err(0u8),").unwrap();
+                                                       writeln!(w, "\t\tErr(e) => crate::c_types::CResultTempl::err(()),").unwrap();
                                                        writeln!(w, "\t}}.into()\n}}").unwrap();
                                                }
                                        } else if path_matches_nongeneric(&trait_path.1, &["Display"]) {
@@ -1137,9 +1137,8 @@ fn writeln_enum<'a, 'b, W: std::io::Write>(w: &mut W, e: &'a syn::ItemEnum, type
        }
        writeln_docs(w, &e.attrs, "");
 
-       if e.generics.lt_token.is_some() {
-               unimplemented!();
-       }
+       let mut gen_types = GenericTypes::new(None);
+       assert!(gen_types.learn_generics(&e.generics, types));
 
        let mut needs_free = false;
 
@@ -1155,21 +1154,31 @@ fn writeln_enum<'a, 'b, W: std::io::Write>(w: &mut W, e: &'a syn::ItemEnum, type
                                if export_status(&field.attrs) == ExportStatus::TestOnly { continue; }
                                writeln_docs(w, &field.attrs, "\t\t");
                                write!(w, "\t\t{}: ", field.ident.as_ref().unwrap()).unwrap();
-                               types.write_c_type(w, &field.ty, None, false);
+                               types.write_c_type(w, &field.ty, Some(&gen_types), false);
                                writeln!(w, ",").unwrap();
                        }
                        write!(w, "\t}}").unwrap();
                } else if let syn::Fields::Unnamed(fields) = &var.fields {
-                       needs_free = true;
-                       write!(w, "(").unwrap();
-                       for (idx, field) in fields.unnamed.iter().enumerate() {
-                               if export_status(&field.attrs) == ExportStatus::TestOnly { continue; }
-                               types.write_c_type(w, &field.ty, None, false);
-                               if idx != fields.unnamed.len() - 1 {
-                                       write!(w, ",").unwrap();
+                       let mut empty_tuple_variant = false;
+                       if fields.unnamed.len() == 1 {
+                               let mut empty_check = Vec::new();
+                               types.write_c_type(&mut empty_check, &fields.unnamed[0].ty, Some(&gen_types), false);
+                               if empty_check.is_empty() {
+                                       empty_tuple_variant = true;
+                               }
+                       }
+                       if !empty_tuple_variant {
+                               needs_free = true;
+                               write!(w, "(").unwrap();
+                               for (idx, field) in fields.unnamed.iter().enumerate() {
+                                       if export_status(&field.attrs) == ExportStatus::TestOnly { continue; }
+                                       types.write_c_type(w, &field.ty, Some(&gen_types), false);
+                                       if idx != fields.unnamed.len() - 1 {
+                                               write!(w, ",").unwrap();
+                                       }
                                }
+                               write!(w, ")").unwrap();
                        }
-                       write!(w, ")").unwrap();
                }
                if var.discriminant.is_some() { unimplemented!(); }
                writeln!(w, ",").unwrap();
@@ -1181,6 +1190,7 @@ fn writeln_enum<'a, 'b, W: std::io::Write>(w: &mut W, e: &'a syn::ItemEnum, type
                        writeln!(w, "\t#[allow(unused)]\n\tpub(crate) fn {} {{\n\t\tmatch {} {{", $fn_sig, if $to_c { "native" } else { "self" }).unwrap();
                        for var in e.variants.iter() {
                                write!(w, "\t\t\t{}{}::{} ", if $to_c { "native" } else { "" }, e.ident, var.ident).unwrap();
+                               let mut empty_tuple_variant = false;
                                if let syn::Fields::Named(fields) = &var.fields {
                                        write!(w, "{{").unwrap();
                                        for field in fields.named.iter() {
@@ -1189,12 +1199,21 @@ fn writeln_enum<'a, 'b, W: std::io::Write>(w: &mut W, e: &'a syn::ItemEnum, type
                                        }
                                        write!(w, "}} ").unwrap();
                                } else if let syn::Fields::Unnamed(fields) = &var.fields {
-                                       write!(w, "(").unwrap();
-                                       for (idx, field) in fields.unnamed.iter().enumerate() {
-                                               if export_status(&field.attrs) == ExportStatus::TestOnly { continue; }
-                                               write!(w, "{}{}, ", if $ref { "ref " } else { "mut " }, ('a' as u8 + idx as u8) as char).unwrap();
+                                       if fields.unnamed.len() == 1 {
+                                               let mut empty_check = Vec::new();
+                                               types.write_c_type(&mut empty_check, &fields.unnamed[0].ty, Some(&gen_types), false);
+                                               if empty_check.is_empty() {
+                                                       empty_tuple_variant = true;
+                                               }
+                                       }
+                                       if !empty_tuple_variant || $to_c {
+                                               write!(w, "(").unwrap();
+                                               for (idx, field) in fields.unnamed.iter().enumerate() {
+                                                       if export_status(&field.attrs) == ExportStatus::TestOnly { continue; }
+                                                       write!(w, "{}{}, ", if $ref { "ref " } else { "mut " }, ('a' as u8 + idx as u8) as char).unwrap();
+                                               }
+                                               write!(w, ") ").unwrap();
                                        }
-                                       write!(w, ") ").unwrap();
                                }
                                write!(w, "=>").unwrap();
 
@@ -1204,9 +1223,9 @@ fn writeln_enum<'a, 'b, W: std::io::Write>(w: &mut W, e: &'a syn::ItemEnum, type
                                                let mut sink = ::std::io::sink();
                                                let mut out: &mut dyn std::io::Write = if $ref { &mut sink } else { w };
                                                let new_var = if $to_c {
-                                                       types.write_to_c_conversion_new_var(&mut out, $field_ident, &$field.ty, None, false)
+                                                       types.write_to_c_conversion_new_var(&mut out, $field_ident, &$field.ty, Some(&gen_types), false)
                                                } else {
-                                                       types.write_from_c_conversion_new_var(&mut out, $field_ident, &$field.ty, None)
+                                                       types.write_from_c_conversion_new_var(&mut out, $field_ident, &$field.ty, Some(&gen_types))
                                                };
                                                if $ref || new_var {
                                                        if $ref {
@@ -1214,9 +1233,9 @@ fn writeln_enum<'a, 'b, W: std::io::Write>(w: &mut W, e: &'a syn::ItemEnum, type
                                                                if new_var {
                                                                        let nonref_ident = format_ident!("{}_nonref", $field_ident);
                                                                        if $to_c {
-                                                                               types.write_to_c_conversion_new_var(w, &nonref_ident, &$field.ty, None, false);
+                                                                               types.write_to_c_conversion_new_var(w, &nonref_ident, &$field.ty, Some(&gen_types), false);
                                                                        } else {
-                                                                               types.write_from_c_conversion_new_var(w, &nonref_ident, &$field.ty, None);
+                                                                               types.write_from_c_conversion_new_var(w, &nonref_ident, &$field.ty, Some(&gen_types));
                                                                        }
                                                                        write!(w, "\n\t\t\t\t").unwrap();
                                                                }
@@ -1234,7 +1253,9 @@ fn writeln_enum<'a, 'b, W: std::io::Write>(w: &mut W, e: &'a syn::ItemEnum, type
                                } else if let syn::Fields::Unnamed(fields) = &var.fields {
                                        write!(w, " {{\n\t\t\t\t").unwrap();
                                        for (idx, field) in fields.unnamed.iter().enumerate() {
-                                               handle_field_a!(field, &format_ident!("{}", ('a' as u8 + idx as u8) as char));
+                                               if !empty_tuple_variant {
+                                                       handle_field_a!(field, &format_ident!("{}", ('a' as u8 + idx as u8) as char));
+                                               }
                                        }
                                } else { write!(w, " ").unwrap(); }
 
@@ -1244,16 +1265,16 @@ fn writeln_enum<'a, 'b, W: std::io::Write>(w: &mut W, e: &'a syn::ItemEnum, type
                                        ($field: expr, $field_ident: expr) => { {
                                                if export_status(&$field.attrs) == ExportStatus::TestOnly { continue; }
                                                if $to_c {
-                                                       types.write_to_c_conversion_inline_prefix(w, &$field.ty, None, false);
+                                                       types.write_to_c_conversion_inline_prefix(w, &$field.ty, Some(&gen_types), false);
                                                } else {
-                                                       types.write_from_c_conversion_prefix(w, &$field.ty, None);
+                                                       types.write_from_c_conversion_prefix(w, &$field.ty, Some(&gen_types));
                                                }
                                                write!(w, "{}{}", $field_ident,
                                                        if $ref { "_nonref" } else { "" }).unwrap();
                                                if $to_c {
-                                                       types.write_to_c_conversion_inline_suffix(w, &$field.ty, None, false);
+                                                       types.write_to_c_conversion_inline_suffix(w, &$field.ty, Some(&gen_types), false);
                                                } else {
-                                                       types.write_from_c_conversion_suffix(w, &$field.ty, None);
+                                                       types.write_from_c_conversion_suffix(w, &$field.ty, Some(&gen_types));
                                                }
                                                write!(w, ",").unwrap();
                                        } }
@@ -1269,12 +1290,14 @@ fn writeln_enum<'a, 'b, W: std::io::Write>(w: &mut W, e: &'a syn::ItemEnum, type
                                        writeln!(w, "\n\t\t\t\t}}").unwrap();
                                        write!(w, "\t\t\t}}").unwrap();
                                } else if let syn::Fields::Unnamed(fields) = &var.fields {
-                                       write!(w, " (").unwrap();
-                                       for (idx, field) in fields.unnamed.iter().enumerate() {
-                                               write!(w, "\n\t\t\t\t\t").unwrap();
-                                               handle_field_b!(field, &format_ident!("{}", ('a' as u8 + idx as u8) as char));
+                                       if !empty_tuple_variant || !$to_c {
+                                               write!(w, " (").unwrap();
+                                               for (idx, field) in fields.unnamed.iter().enumerate() {
+                                                       write!(w, "\n\t\t\t\t\t").unwrap();
+                                                       handle_field_b!(field, &format_ident!("{}", ('a' as u8 + idx as u8) as char));
+                                               }
+                                               writeln!(w, "\n\t\t\t\t)").unwrap();
                                        }
-                                       writeln!(w, "\n\t\t\t\t)").unwrap();
                                        write!(w, "\t\t\t}}").unwrap();
                                }
                                writeln!(w, ",").unwrap();