+ ret = ret + lastchar
+ if char.isupper() and not lastund:
+ ret = ret + "_"
+ lastund = True
+ else:
+ lastund = False
+ lastchar = char
+ if char.isnumeric():
+ lastund = True
+ return (ret + lastchar.lower()).strip("_")
+
+def doc_to_field_nullable(doc):
+ if doc is None:
+ return False
+ for line in doc.splitlines():
+ if "Note that this (or a relevant inner pointer) may be NULL or all-0s to represent None" in line:
+ return True
+ return False
+
+def doc_to_params_ret_nullable(doc):
+ if doc is None:
+ return (set(), False)
+ params = set()
+ ret_null = False
+ for line in doc.splitlines():
+ if "may be NULL or all-0s to represent None" not in line:
+ continue
+ if "Note that the return value" in line:
+ ret_null = True
+ elif "Note that " in line:
+ param = line.split("Note that ")[1].split(" ")[0]
+ params.add(param)
+ return (params, ret_null)
+
+unitary_enums = set()
+# Map from enum name to "contains trait object"
+complex_enums = {}
+opaque_structs = set()
+trait_structs = {}
+result_types = set()
+tuple_types = {}
+
+var_is_arr_regex = re.compile("\(\* ?([A-za-z0-9_]*)\)\[([a-z0-9]*)\]")
+var_ty_regex = re.compile("([A-za-z_0-9]*)(.*)")
+java_c_types_none_allowed = True # Unset when we do the real pass that populates the above sets
+def java_c_types(fn_arg, ret_arr_len):
+ fn_arg = fn_arg.strip()
+ if fn_arg.startswith("MUST_USE_RES "):
+ fn_arg = fn_arg[13:]
+ is_const = False
+ if fn_arg.startswith("const "):
+ fn_arg = fn_arg[6:]
+ is_const = True
+ if fn_arg.startswith("struct "):
+ fn_arg = fn_arg[7:]
+ if fn_arg.startswith("enum "):
+ fn_arg = fn_arg[5:]
+ nonnull_ptr = "NONNULL_PTR" in fn_arg
+ fn_arg = fn_arg.replace("NONNULL_PTR", "")
+
+ is_ptr = False
+ take_by_ptr = False
+ rust_obj = None
+ arr_access = None
+ java_hu_ty = None
+ if fn_arg.startswith("LDKThirtyTwoBytes"):
+ fn_arg = "uint8_t (*" + fn_arg[18:] + ")[32]"
+ assert var_is_arr_regex.match(fn_arg[8:])
+ rust_obj = "LDKThirtyTwoBytes"
+ arr_access = "data"
+ elif fn_arg.startswith("LDKThirtyTwoU16s"):
+ fn_arg = "uint16_t (*" + fn_arg[17:] + ")[32]"
+ assert var_is_arr_regex.match(fn_arg[9:])
+ rust_obj = "LDKThirtyTwoU16s"
+ arr_access = "data"
+ elif fn_arg.startswith("LDKU128"):
+ if fn_arg == "LDKU128":
+ fn_arg = "LDKU128 arg"
+ if fn_arg.startswith("LDKU128*") or fn_arg.startswith("LDKU128 *"):
+ fn_arg = "uint8_t (" + fn_arg[8:] + ")[16]"
+ else:
+ fn_arg = "uint8_t (*" + fn_arg[8:] + ")[16]"
+ assert var_is_arr_regex.match(fn_arg[8:])
+ rust_obj = "LDKU128"
+ arr_access = "le_bytes"
+ elif fn_arg.startswith("LDKPublicKey"):
+ fn_arg = "uint8_t (*" + fn_arg[13:] + ")[33]"
+ assert var_is_arr_regex.match(fn_arg[8:])
+ rust_obj = "LDKPublicKey"
+ arr_access = "compressed_form"
+ elif fn_arg.startswith("LDKTweakedPublicKey"):
+ fn_arg = "uint8_t (*" + fn_arg[21:] + ")[32]"
+ assert var_is_arr_regex.match(fn_arg[8:])
+ rust_obj = "LDKTweakedPublicKey"
+ arr_access = "x_coordinate"
+ elif fn_arg.startswith("LDKSecretKey"):
+ fn_arg = "uint8_t (*" + fn_arg[13:] + ")[32]"
+ assert var_is_arr_regex.match(fn_arg[8:])
+ rust_obj = "LDKSecretKey"
+ arr_access = "bytes"
+ elif fn_arg.startswith("LDKECDSASignature"):
+ fn_arg = "uint8_t (*" + fn_arg[18:] + ")[64]"
+ assert var_is_arr_regex.match(fn_arg[8:])
+ rust_obj = "LDKECDSASignature"
+ arr_access = "compact_form"
+ elif fn_arg.startswith("LDKSchnorrSignature"):
+ fn_arg = "uint8_t (*" + fn_arg[20:] + ")[64]"
+ assert var_is_arr_regex.match(fn_arg[8:])
+ rust_obj = "LDKSchnorrSignature"
+ arr_access = "compact_form"
+ elif fn_arg.startswith("LDKRecoverableSignature"):
+ fn_arg = "uint8_t (*" + fn_arg[24:] + ")[68]"
+ assert var_is_arr_regex.match(fn_arg[8:])
+ rust_obj = "LDKRecoverableSignature"
+ arr_access = "serialized_form"
+ elif fn_arg.startswith("LDKThreeBytes"):
+ fn_arg = "uint8_t (*" + fn_arg[14:] + ")[3]"
+ assert var_is_arr_regex.match(fn_arg[8:])
+ rust_obj = "LDKThreeBytes"
+ arr_access = "data"
+ elif fn_arg.startswith("LDKFourBytes"):
+ fn_arg = "uint8_t (*" + fn_arg[13:] + ")[4]"
+ assert var_is_arr_regex.match(fn_arg[8:])
+ rust_obj = "LDKFourBytes"
+ arr_access = "data"
+ elif fn_arg.startswith("LDKSixteenBytes"):
+ fn_arg = "uint8_t (*" + fn_arg[16:] + ")[16]"
+ assert var_is_arr_regex.match(fn_arg[8:])
+ rust_obj = "LDKSixteenBytes"
+ arr_access = "data"
+ elif fn_arg.startswith("LDKTwentyBytes"):
+ fn_arg = "uint8_t (*" + fn_arg[15:] + ")[20]"
+ assert var_is_arr_regex.match(fn_arg[8:])
+ rust_obj = "LDKTwentyBytes"
+ arr_access = "data"
+ elif fn_arg.startswith("LDKTwelveBytes"):
+ fn_arg = "uint8_t (*" + fn_arg[15:] + ")[12]"
+ assert var_is_arr_regex.match(fn_arg[8:])
+ rust_obj = "LDKTwelveBytes"
+ arr_access = "data"
+ elif fn_arg.startswith("LDKu8slice"):
+ fn_arg = "uint8_t (*" + fn_arg[11:] + ")[datalen]"
+ assert var_is_arr_regex.match(fn_arg[8:])
+ rust_obj = "LDKu8slice"
+ arr_access = "data"
+ elif fn_arg.startswith("LDKCVec_u8Z"):
+ fn_arg = "uint8_t (*" + fn_arg[12:] + ")[datalen]"
+ rust_obj = "LDKCVec_u8Z"
+ assert var_is_arr_regex.match(fn_arg[8:])
+ arr_access = "data"
+ elif fn_arg.startswith("LDKTransaction ") or fn_arg == "LDKTransaction":
+ fn_arg = "uint8_t (*" + fn_arg[15:] + ")[datalen]"
+ rust_obj = "LDKTransaction"
+ assert var_is_arr_regex.match(fn_arg[8:])
+ arr_access = "data"
+ elif fn_arg.startswith("LDKTransactionOutputs "):
+ fn_arg = "C2Tuple_ThirtyTwoBytesCVec_C2Tuple_u32TxOutZZZ"
+ rust_obj = "C2Tuple_ThirtyTwoBytesCVec_C2Tuple_u32TxOutZZZ"
+ elif fn_arg.startswith("LDKWitness ") or fn_arg == "LDKWitness":
+ if len(fn_arg) > 12 and fn_arg[11] == "*":
+ fn_arg = "uint8_t (" + fn_arg[11:] + ")[datalen]"
+ else:
+ fn_arg = "uint8_t (*" + fn_arg[11:] + ")[datalen]"
+ rust_obj = "LDKWitness"
+ assert var_is_arr_regex.match(fn_arg[8:])
+ arr_access = "data"
+ elif fn_arg.startswith("LDKCVec_"):
+ is_ptr = False
+ if "*" in fn_arg:
+ fn_arg = fn_arg.replace("*", "")