@@ -16,10 +16,21 @@ def __init__(self, java_c_types, consts, opaque_structs, clone_fns, unitary_enum
1616
1717 def map_type (self , fn_arg , print_void , ret_arr_len , is_free , holds_ref ):
1818 ty_info = self .java_c_types (fn_arg , ret_arr_len )
19- mapped_info = self .map_type_with_info (ty_info , print_void , ret_arr_len , is_free , holds_ref )
19+ mapped_info = self .map_type_with_info (ty_info , print_void , ret_arr_len , is_free , holds_ref , False )
2020 return mapped_info
2121
22- def map_type_with_info (self , ty_info , print_void , ret_arr_len , is_free , holds_ref ):
22+ def map_nullable_type (self , fn_arg , print_void , ret_arr_len , is_free , holds_ref ):
23+ ty_info = self .java_c_types (fn_arg , ret_arr_len )
24+ mapped_info = self .map_type_with_info (ty_info , print_void , ret_arr_len , is_free , holds_ref , True )
25+ return mapped_info
26+
27+ def map_type_with_info (self , ty_info , print_void , ret_arr_len , is_free , holds_ref , is_nullable ):
28+ mapped_info = self ._do_map_type_with_info (ty_info , print_void , ret_arr_len , is_free , holds_ref , is_nullable )
29+ if is_nullable :
30+ mapped_info .nullable = True
31+ return mapped_info
32+
33+ def _do_map_type_with_info (self , ty_info , print_void , ret_arr_len , is_free , holds_ref , is_nullable ):
2334 if ty_info .c_ty == "void" :
2435 if not print_void :
2536 return ConvInfo (ty_info = ty_info , arg_name = ty_info .var_name ,
@@ -85,7 +96,7 @@ def map_type_with_info(self, ty_info, print_void, ret_arr_len, is_free, holds_re
8596 # function itself, resulting in a segfault. Thus, we manually check and ensure we don't clone for
8697 # ChannelMonitors inside of vecs.
8798 ty_info .subty .requires_clone = False
88- subty = self .map_type_with_info (ty_info .subty , False , None , is_free , holds_ref )
99+ subty = self .map_type_with_info (ty_info .subty , False , None , is_free , holds_ref , False )
89100 arg_conv = ty_info .rust_obj + " " + arr_name + "_constr;\n "
90101 pf = ""
91102 if ty_info .is_ptr :
@@ -127,32 +138,43 @@ def map_type_with_info(self, ty_info, print_void, ret_arr_len, is_free, holds_re
127138 if ty_info .is_ptr :
128139 arg_conv += "\n \t " + arr_name + "_ptr = &" + arr_name + "_constr;\n }"
129140
130- ret_conv = (ty_info .rust_obj + " " + arr_name + "_var = " , "" )
141+ if is_nullable :
142+ ret_conv = (ty_info .rust_obj + " *" + arr_name + "_var_ptr = " , "" )
143+ else :
144+ ret_conv = (ty_info .rust_obj + " " + arr_name + "_var = " , "" )
131145 if subty .ret_conv is None :
132146 ret_conv = ("DUMMY" , "DUMMY" )
133147 else :
134- ret_conv = (ret_conv [0 ], ";\n " + ty_info .c_ty + " " + arr_name + "_arr = " + self .consts .create_native_arr_call (arr_name + "_var." + arr_len , ty_info ) + ";\n " )
148+ ret_conv = (ret_conv [0 ], ";\n " + ty_info .c_ty + " " + arr_name + "_arr = NULL;\n " )
149+ indent = ""
150+ if is_nullable :
151+ ret_conv = (ret_conv [0 ], ret_conv [1 ] + "if (" + arr_name + " != NULL) {\n " )
152+ ret_conv = (ret_conv [0 ], ret_conv [1 ] + "\t " + ty_info .rust_obj + " " + arr_name + "_var = *" + arr_name + "_var_ptr;\n " )
153+ indent = "\t "
154+ ret_conv = (ret_conv [0 ], ret_conv [1 ] + indent + arr_name + "_arr = " + self .consts .create_native_arr_call (arr_name + "_var." + arr_len , ty_info ) + ";\n " )
135155 get_ptr_call = self .consts .get_native_arr_ptr_call (ty_info )
136156 if get_ptr_call is not None :
137- ret_conv = (ret_conv [0 ], ret_conv [1 ] + subty .c_ty + " *" + arr_name + "_arr_ptr = " + get_ptr_call [0 ] + arr_name + "_arr" + get_ptr_call [1 ] + ";\n " )
138- ret_conv = (ret_conv [0 ], ret_conv [1 ] + "for (size_t " + idxc + " = 0; " + idxc + " < " + arr_name + "_var." + arr_len + "; " + idxc + "++) {\n " )
139- ret_conv = (ret_conv [0 ], ret_conv [1 ] + "\t " + subty .ret_conv [0 ].replace ("\n " , "\n \t " ))
140- ret_conv = (ret_conv [0 ], ret_conv [1 ] + arr_name + "_var." + ty_info .arr_access + "[" + idxc + "]" + subty .ret_conv [1 ].replace ("\n " , "\n \t " ) )
157+ ret_conv = (ret_conv [0 ], ret_conv [1 ] + indent + subty .c_ty + " *" + arr_name + "_arr_ptr = " + get_ptr_call [0 ] + arr_name + "_arr" + get_ptr_call [1 ] + ";\n " )
158+ ret_conv = (ret_conv [0 ], ret_conv [1 ] + indent + "for (size_t " + idxc + " = 0; " + idxc + " < " + arr_name + "_var." + arr_len + "; " + idxc + "++) {\n " )
159+ ret_conv = (ret_conv [0 ], ret_conv [1 ] + indent + "\t " + subty .ret_conv [0 ].replace ("\n " , "\n \t " + indent ))
160+ ret_conv = (ret_conv [0 ], ret_conv [1 ] + indent + arr_name + "_var." + ty_info .arr_access + "[" + idxc + "]" + subty .ret_conv [1 ].replace ("\n " , "\n \t " + indent ) + " \n " )
141161 if get_ptr_call is not None :
142- ret_conv = (ret_conv [0 ], ret_conv [1 ] + " \n \ t " + arr_name + "_arr_ptr[" + idxc + "] = " + subty .ret_conv_name + ";\n } " )
162+ ret_conv = (ret_conv [0 ], ret_conv [1 ] + indent + " \ t " + arr_name + "_arr_ptr[" + idxc + "] = " + subty .ret_conv_name + ";\n " + indent + "} \n " )
143163 else :
144- ret_conv = (ret_conv [0 ], ret_conv [1 ] + " \n \ t " + self .consts .get_native_arr_entry_call (ty_info , arr_name + "_arr" , idxc , subty .ret_conv_name ) + ";\n } " )
164+ ret_conv = (ret_conv [0 ], ret_conv [1 ] + indent + " \ t " + self .consts .get_native_arr_entry_call (ty_info , arr_name + "_arr" , idxc , subty .ret_conv_name ) + ";\n " + indent + "} \n " )
145165 cleanup = self .consts .release_native_arr_ptr_call (ty_info , arr_name + "_arr" , arr_name + "_arr_ptr" )
146166 if cleanup is not None :
147- ret_conv = (ret_conv [0 ], ret_conv [1 ] + "\n " + cleanup + ";" )
148- if not holds_ref :
149- # XXX: The commented if's are a bit smarter freeing, but we need to be a nudge smarter still
150- # Note that we don't drop the full vec here - we're passing ownership to java (or have cloned) or free'd by now!
151- ret_conv = (ret_conv [0 ], ret_conv [1 ] + "\n FREE(" + arr_name + "_var." + ty_info .arr_access + ");" )
152- #if subty.rust_obj is not None and subty.rust_obj in self.opaque_structs:
153- # ret_conv = (ret_conv[0], ret_conv[1] + "\nFREE(" + arr_name + "_var." + ty_info.arr_access + ");")
154- #else:
155- # ret_conv = (ret_conv[0], ret_conv[1] + "\n" + ty_info.rust_obj.replace("LDK", "") + "_free(" + arr_name + "_var);")
167+ ret_conv = (ret_conv [0 ], ret_conv [1 ] + indent + cleanup + ";" )
168+ if not holds_ref and not is_nullable :
169+ # XXX: The commented if's are a bit smarter freeing, but we need to be a nudge smarter still
170+ # Note that we don't drop the full vec here - we're passing ownership to java (or have cloned) or free'd by now!
171+ ret_conv = (ret_conv [0 ], ret_conv [1 ] + "\n " + indent + "FREE(" + arr_name + "_var." + ty_info .arr_access + ");" )
172+ #if subty.rust_obj is not None and subty.rust_obj in self.opaque_structs:
173+ # ret_conv = (ret_conv[0], ret_conv[1] + "\nFREE(" + arr_name + "_var." + ty_info.arr_access + ");")
174+ #else:
175+ # ret_conv = (ret_conv[0], ret_conv[1] + "\n" + ty_info.rust_obj.replace("LDK", "") + "_free(" + arr_name + "_var);")
176+ if is_nullable :
177+ ret_conv = (ret_conv [0 ], ret_conv [1 ] + "\n }" )
156178
157179 to_hu_conv = None
158180 to_hu_conv_name = None
@@ -185,6 +207,7 @@ def map_type_with_info(self, ty_info, print_void, ret_arr_len, is_free, holds_re
185207 arg_conv = arg_conv , arg_conv_name = arg_conv_name , arg_conv_cleanup = arg_conv_cleanup ,
186208 ret_conv = ret_conv , ret_conv_name = arr_name + "_arr" , to_hu_conv = to_hu_conv , to_hu_conv_name = to_hu_conv_name , from_hu_conv = from_hu_conv )
187209 elif ty_info .java_ty == "String" :
210+ assert not is_nullable
188211 if not is_free :
189212 arg_conv = "LDKStr " + ty_info .var_name + "_conv = " + self .consts .str_ref_to_c_call (ty_info .var_name ) + ";"
190213 arg_conv_name = ty_info .var_name + "_conv"
@@ -221,6 +244,7 @@ def map_type_with_info(self, ty_info, print_void, ret_arr_len, is_free, holds_re
221244 arg_conv = None , arg_conv_name = "arg" , arg_conv_cleanup = None ,
222245 ret_conv = None , ret_conv_name = None , to_hu_conv = "TODO 8" , to_hu_conv_name = None , from_hu_conv = None )
223246 elif ty_info .is_native_primitive :
247+ assert not is_nullable
224248 return ConvInfo (ty_info = ty_info , arg_name = ty_info .var_name ,
225249 arg_conv = None , arg_conv_name = ty_info .var_name , arg_conv_cleanup = None ,
226250 ret_conv = None , ret_conv_name = None , to_hu_conv = None , to_hu_conv_name = None , from_hu_conv = None )
@@ -254,20 +278,27 @@ def map_type_with_info(self, ty_info, print_void, ret_arr_len, is_free, holds_re
254278 "// Thus, after this call, " + ty_info .var_name + " is reset to null and is now a dummy object.\n " + ty_info .var_name + ".ptr = 0" )
255279
256280 opaque_ret_conv_suf = ";\n "
281+ opaque_ret_conv_suf += "uint64_t " + ty_info .var_name + "_ref = 0;\n "
282+ indent = ""
283+ if is_nullable :
284+ opaque_ret_conv_suf += "if ((uint64_t)" + ty_info .var_name + "_var.inner > 4096) {\n "
285+ indent = "\t "
257286 if not holds_ref and ty_info .is_ptr and (ty_info .rust_obj .replace ("LDK" , "" ) + "_clone" ) in self .clone_fns : # is_ptr, not holds_ref implies passing a pointed-to value to java, which needs copied
258- opaque_ret_conv_suf = opaque_ret_conv_suf + ty_info .var_name + "_var = " + ty_info .rust_obj .replace ("LDK" , "" ) + "_clone(" + ty_info .var_name + ");\n "
287+ opaque_ret_conv_suf += indent + ty_info .var_name + "_var = " + ty_info .rust_obj .replace ("LDK" , "" ) + "_clone(" + ty_info .var_name + ");\n "
259288 elif not holds_ref and ty_info .is_ptr :
260- opaque_ret_conv_suf = opaque_ret_conv_suf + "// Warning: we may need a move here but no clone is available for " + ty_info .rust_obj + "\n "
289+ opaque_ret_conv_suf += indent + "// Warning: we may need a move here but no clone is available for " + ty_info .rust_obj + "\n "
261290
262- opaque_ret_conv_suf = opaque_ret_conv_suf + "CHECK((((uint64_t)" + ty_info .var_name + "_var.inner) & 1) == 0); // We rely on a free low bit, malloc guarantees this.\n "
263- opaque_ret_conv_suf = opaque_ret_conv_suf + "CHECK((((uint64_t)&" + ty_info .var_name + "_var) & 1) == 0); // We rely on a free low bit, pointer alignment guarantees this.\n "
291+ opaque_ret_conv_suf += indent + "CHECK((((uint64_t)" + ty_info .var_name + "_var.inner) & 1) == 0); // We rely on a free low bit, malloc guarantees this.\n "
292+ opaque_ret_conv_suf += indent + "CHECK((((uint64_t)&" + ty_info .var_name + "_var) & 1) == 0); // We rely on a free low bit, pointer alignment guarantees this.\n "
264293 if holds_ref :
265- opaque_ret_conv_suf = opaque_ret_conv_suf + "uint64_t " + ty_info .var_name + "_ref = (uint64_t)" + ty_info .var_name + "_var.inner & ~1;"
294+ opaque_ret_conv_suf += indent + ty_info .var_name + "_ref = (uint64_t)" + ty_info .var_name + "_var.inner & ~1;"
266295 else :
267- opaque_ret_conv_suf = opaque_ret_conv_suf + "uint64_t " + ty_info .var_name + "_ref = (uint64_t)" + ty_info .var_name + "_var.inner;\n "
268- opaque_ret_conv_suf = opaque_ret_conv_suf + "if (" + ty_info .var_name + "_var.is_owned) {\n "
269- opaque_ret_conv_suf = opaque_ret_conv_suf + "\t " + ty_info .var_name + "_ref |= 1;\n "
270- opaque_ret_conv_suf = opaque_ret_conv_suf + "}"
296+ opaque_ret_conv_suf += indent + ty_info .var_name + "_ref = (uint64_t)" + ty_info .var_name + "_var.inner;\n "
297+ opaque_ret_conv_suf += indent + "if (" + ty_info .var_name + "_var.is_owned) {\n "
298+ opaque_ret_conv_suf += indent + "\t " + ty_info .var_name + "_ref |= 1;\n "
299+ opaque_ret_conv_suf += indent + "}"
300+ if is_nullable :
301+ opaque_ret_conv_suf += "\n }"
271302
272303 to_hu_conv_sfx = ""
273304 if not ty_info .is_ptr or holds_ref :
@@ -289,6 +320,7 @@ def map_type_with_info(self, ty_info, print_void, ret_arr_len, is_free, holds_re
289320 to_hu_conv_name = ty_info .var_name + "_hu_conv" ,
290321 from_hu_conv = from_hu_conv )
291322
323+ assert not is_nullable
292324 if not ty_info .is_ptr :
293325 if ty_info .rust_obj in self .unitary_enums :
294326 (ret_pfx , ret_sfx ) = self .consts .c_unitary_enum_to_native_call (ty_info )
0 commit comments