Skip to content

Commit 62e26d3

Browse files
committed
Make nullable complex arrays get restructured properly for native passing.
1 parent 029f3ad commit 62e26d3

File tree

5 files changed

+71
-25
lines changed

5 files changed

+71
-25
lines changed

bindings/LDK/Bindings.swift

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4067,15 +4067,16 @@ withUnsafePointer(to: htlc.cOpaqueStruct!) { (htlcPointer: UnsafePointer<LDKHTLC
40674067

40684068
var first_hopsPointer: UnsafeMutablePointer<LDKCVec_ChannelDetailsZ>? = nil
40694069
if let first_hopsUnwrapped = first_hops {
4070-
first_hopsPointer = UnsafeMutablePointer<LDKCVec_ChannelDetailsZ>.allocate(capacity: 1)
4071-
first_hopsPointer!.initialize(to: Bindings.new_LDKCVec_ChannelDetailsZWrapper(array: first_hopsUnwrapped).cOpaqueStruct!)
4072-
}
4073-
4074-
let first_hopsUnwrapped = first_hops.map { (first_hopsCurrentValue) in
4070+
4071+
let first_hopsUnwrapped = first_hopsUnwrapped.map { (first_hopsCurrentValue) in
40754072
first_hopsCurrentValue
40764073
.danglingClone().cOpaqueStruct!
40774074
}
40784075

4076+
first_hopsPointer = UnsafeMutablePointer<LDKCVec_ChannelDetailsZ>.allocate(capacity: 1)
4077+
first_hopsPointer!.initialize(to: Bindings.new_LDKCVec_ChannelDetailsZWrapper(array: first_hopsUnwrapped).cOpaqueStruct!)
4078+
}
4079+
40794080
let last_hopsUnwrapped = last_hops.map { (last_hopsCurrentValue) in
40804081
last_hopsCurrentValue
40814082
.danglingClone().cOpaqueStruct!
@@ -4088,7 +4089,7 @@ withUnsafePointer(to: htlc.cOpaqueStruct!) { (htlcPointer: UnsafePointer<LDKHTLC
40884089

40894090
return withUnsafePointer(to: network.cOpaqueStruct!) { (networkPointer: UnsafePointer<LDKNetworkGraph>) in
40904091

4091-
Result_RouteLightningErrorZ(pointer: get_keysend_route(Bindings.new_LDKPublicKey(array: our_node_id), networkPointer, Bindings.new_LDKPublicKey(array: payee), first_hopsUnwrapped, last_hopsWrapper.dangle().cOpaqueStruct!, final_value_msat, final_cltv, logger.cOpaqueStruct!))
4092+
Result_RouteLightningErrorZ(pointer: get_keysend_route(Bindings.new_LDKPublicKey(array: our_node_id), networkPointer, Bindings.new_LDKPublicKey(array: payee), first_hopsPointer, last_hopsWrapper.dangle().cOpaqueStruct!, final_value_msat, final_cltv, logger.cOpaqueStruct!))
40924093

40934094
}
40944095

bindings/LDK/structs/ChainMonitor.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ public class ChainMonitor: NativeTypeWrapper {
1313

1414
var chain_sourcePointer: UnsafeMutablePointer<LDKFilter>? = nil
1515
if let chain_sourceUnwrapped = chain_source {
16+
1617
chain_sourcePointer = UnsafeMutablePointer<LDKFilter>.allocate(capacity: 1)
1718
chain_sourcePointer!.initialize(to: chain_sourceUnwrapped.cOpaqueStruct!)
1819
}

bindings/LDK/structs/NetGraphMsgHandler.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ public class NetGraphMsgHandler: NativeTypeWrapper {
1313

1414
var chain_accessPointer: UnsafeMutablePointer<LDKAccess>? = nil
1515
if let chain_accessUnwrapped = chain_access {
16+
1617
chain_accessPointer = UnsafeMutablePointer<LDKAccess>.allocate(capacity: 1)
1718
chain_accessPointer!.initialize(to: chain_accessUnwrapped.cOpaqueStruct!)
1819
}
@@ -47,6 +48,7 @@ public class NetGraphMsgHandler: NativeTypeWrapper {
4748

4849
var chain_accessPointer: UnsafeMutablePointer<LDKAccess>? = nil
4950
if let chain_accessUnwrapped = chain_access {
51+
5052
chain_accessPointer = UnsafeMutablePointer<LDKAccess>.allocate(capacity: 1)
5153
chain_accessPointer!.initialize(to: chain_accessUnwrapped.cOpaqueStruct!)
5254
}

bindings/LDK/structs/NetworkGraph.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ NetworkGraph_update_node_from_unsigned_announcement(this_argPointer, msgPointer)
9292

9393
var chain_accessPointer: UnsafeMutablePointer<LDKAccess>? = nil
9494
if let chain_accessUnwrapped = chain_access {
95+
9596
chain_accessPointer = UnsafeMutablePointer<LDKAccess>.allocate(capacity: 1)
9697
chain_accessPointer!.initialize(to: chain_accessUnwrapped.cOpaqueStruct!)
9798
}
@@ -108,6 +109,7 @@ NetworkGraph_update_channel_from_announcement(this_argPointer, msgPointer, chain
108109

109110
var chain_accessPointer: UnsafeMutablePointer<LDKAccess>? = nil
110111
if let chain_accessUnwrapped = chain_access {
112+
111113
chain_accessPointer = UnsafeMutablePointer<LDKAccess>.allocate(capacity: 1)
112114
chain_accessPointer!.initialize(to: chain_accessUnwrapped.cOpaqueStruct!)
113115
}

src/conversion_helper.py

Lines changed: 59 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,27 +10,32 @@ class ConversionHelper:
1010
freeable_types = set()
1111

1212
@classmethod
13-
def prepare_swift_to_native_arguments(cls, argument_types, is_trait_callback=False, force_pass_instance=False, is_free_method=False, is_returned_value_freeable=False):
13+
def prepare_swift_to_native_arguments(cls, argument_types, is_trait_callback=False, force_pass_instance=False, is_free_method=False, is_returned_value_freeable=False, array_unwrapping_preparation_only = False):
1414
swift_arguments = []
15+
swift_redirection_arguments = []
1516
native_arguments = []
1617
pointer_wrapping_prefix = ''
1718
pointer_wrapping_suffix = ''
1819
native_call_prep = ''
1920
pointer_wrapping_depth = 0
2021
static_eligible = True
2122
non_cloneable_argument_indices_passed_by_ownership = []
23+
has_unwrapped_arrays = False
2224
for argument_index, current_argument_details in enumerate(argument_types):
2325
pass_instance = False
2426
argument_name = current_argument_details.var_name
2527
passed_argument_name = argument_name
2628
is_pointer_to_array = False
29+
is_array_wrapper_extraction_required = False
30+
array_wrapper_extraction = ''
2731

2832
# if passed_argument_name == 'init': # illegal in swift
2933
# passed_argument_name = 'initValue'
3034

3135
mutabilityIndicatorSuffix = ''
3236
clone_infix = ''
3337
cloneability_lookup = 'x-uncloneable'
38+
individual_cloneability_lookup = None
3439
if current_argument_details.rust_obj is not None:
3540
cloneability_lookup = current_argument_details.rust_obj
3641
if cloneability_lookup.startswith('LDK'):
@@ -45,6 +50,43 @@ def prepare_swift_to_native_arguments(cls, argument_types, is_trait_callback=Fal
4550
passed_argument_name = 'self'
4651
static_eligible = False
4752

53+
swift_argument_type = current_argument_details.swift_type
54+
if not pass_instance:
55+
if swift_argument_type == 'TxOut':
56+
swift_argument_type = 'LDKTxOut'
57+
58+
if TypeParsingRegeces.WRAPPER_TYPE_ARRAY_BRACKET_REGEX.search(swift_argument_type):
59+
if is_trait_callback and not array_unwrapping_preparation_only:
60+
swift_argument_type = TypeParsingRegeces.WRAPPER_TYPE_ARRAY_BRACKET_REGEX.sub('[LDK', swift_argument_type)
61+
swift_argument_type = swift_argument_type.replace('[LDKResult_', '[LDKCResult_').replace('[LDKTuple_', '[LDKCTuple_')
62+
has_unwrapped_arrays = True
63+
else:
64+
is_array_wrapper_extraction_required = True
65+
individual_cloneability_lookup = swift_argument_type.lstrip('[').rstrip(']')
66+
wrapper_depth = int((len(swift_argument_type) - len(individual_cloneability_lookup)) / 2)
67+
if individual_cloneability_lookup.startswith('Result_') or individual_cloneability_lookup.startswith('Tuple_'):
68+
individual_cloneability_lookup = f'C{individual_cloneability_lookup}'
69+
is_individual_cloneable = individual_cloneability_lookup in cloneable_types
70+
individual_clone_infix = '.danglingClone()'
71+
if not is_individual_cloneable:
72+
individual_clone_infix = '.dangle()'
73+
print(f'Non-cloneable array entry detected for type {swift_argument_type}')
74+
passed_argument_name = f'{argument_name}Unwrapped'
75+
map_prefix = f'''.map {{ ({argument_name}CurrentValue) in
76+
{argument_name}CurrentValue''' * wrapper_depth
77+
map_suffix = '}' * wrapper_depth
78+
input_argument_name = argument_name
79+
is_nullable_array_argument = current_argument_details.is_ptr and not pass_instance and not current_argument_details.non_nullable
80+
if is_nullable_array_argument:
81+
input_argument_name = passed_argument_name
82+
array_wrapper_extraction = f'''
83+
let {passed_argument_name} = {input_argument_name}{map_prefix}
84+
{individual_clone_infix}.cOpaqueStruct!
85+
{map_suffix}
86+
'''
87+
if not is_nullable_array_argument:
88+
native_call_prep += array_wrapper_extraction
89+
4890
if current_argument_details.is_ptr:
4991
passed_argument_name = argument_name + 'Pointer'
5092
if argument_name == 'init':
@@ -70,7 +112,7 @@ def prepare_swift_to_native_arguments(cls, argument_types, is_trait_callback=Fal
70112
# }
71113
# the \n\t will add a bunch of extra lines, but this file will be easier to read
72114

73-
if requires_mutability:
115+
if requires_mutability and not array_unwrapping_preparation_only:
74116
if pass_instance or non_nullable:
75117
native_call_prep += f'''
76118
let {passed_argument_name} = UnsafeMutablePointer<{current_argument_details.rust_obj}>.allocate(capacity: 1)
@@ -95,6 +137,7 @@ def prepare_swift_to_native_arguments(cls, argument_types, is_trait_callback=Fal
95137
native_call_prep += f'''
96138
var {passed_argument_name}: UnsafeMutablePointer<{current_argument_details.rust_obj}>? = nil
97139
if let {argument_name}Unwrapped = {argument_name} {{
140+
{array_wrapper_extraction}
98141
{passed_argument_name} = UnsafeMutablePointer<{current_argument_details.rust_obj}>.allocate(capacity: 1)
99142
{passed_argument_name}!.initialize(to: {initialization_target})
100143
}}
@@ -116,8 +159,7 @@ def prepare_swift_to_native_arguments(cls, argument_types, is_trait_callback=Fal
116159
elif current_argument_details.rust_obj in ConversionHelper.trait_structs:
117160
pass
118161
elif current_argument_details.rust_obj.startswith('LDK') and not current_argument_details.swift_type.startswith('[') and not is_free_method:
119-
non_cloneable_argument_indices_passed_by_ownership.append(argument_index)
120-
# clone_infix = '.dangle()'
162+
non_cloneable_argument_indices_passed_by_ownership.append(argument_index) # clone_infix = '.dangle()'
121163
if current_argument_details.rust_obj is not None and (
122164
'Option' in current_argument_details.rust_obj or 'Tuple' in current_argument_details.rust_obj or 'Result' in current_argument_details.rust_obj) and not current_argument_details.rust_obj.startswith(
123165
'['):
@@ -129,15 +171,12 @@ def prepare_swift_to_native_arguments(cls, argument_types, is_trait_callback=Fal
129171
if current_argument_details.swift_type.startswith('[') or current_argument_details.swift_type == 'String':
130172
mutabilityIndicatorSuffix = '?'
131173

132-
swift_argument_type = current_argument_details.swift_type
133174
if not pass_instance:
134-
if swift_argument_type == 'TxOut':
135-
swift_argument_type = 'LDKTxOut'
136-
137-
if TypeParsingRegeces.WRAPPER_TYPE_ARRAY_BRACKET_REGEX.search(swift_argument_type):
138-
swift_argument_type = TypeParsingRegeces.WRAPPER_TYPE_ARRAY_BRACKET_REGEX.sub('[LDK', swift_argument_type)
139-
swift_argument_type = swift_argument_type.replace('[LDKResult_', '[LDKCResult_').replace('[LDKTuple_', '[LDKCTuple_')
140175
swift_arguments.append(f'{argument_name}: {swift_argument_type}{mutabilityIndicatorSuffix}')
176+
if is_array_wrapper_extraction_required and array_unwrapping_preparation_only:
177+
swift_redirection_arguments.append(f'{argument_name}: {passed_argument_name}')
178+
else:
179+
swift_redirection_arguments.append(f'{argument_name}: {argument_name}')
141180

142181
# native_arguments.append(f'{passed_argument_name}')
143182
if current_argument_details.rust_obj == 'LDK' + swift_argument_type and not current_argument_details.is_ptr:
@@ -146,7 +185,7 @@ def prepare_swift_to_native_arguments(cls, argument_types, is_trait_callback=Fal
146185
native_arguments.append(f'{passed_argument_name}{clone_infix}.cOpaqueStruct!')
147186
elif current_argument_details.rust_obj is not None and current_argument_details.rust_obj.startswith('LDK') and swift_argument_type.startswith('[') and not is_pointer_to_array:
148187
# if current_argument_details.swift_type == '[UInt8]' and not current_argument_details.swift_raw_type.startswith('LDKC'):
149-
if current_argument_details.rust_obj in pointer_iterating_vector_types:
188+
if current_argument_details.rust_obj in pointer_iterating_vector_types and not array_unwrapping_preparation_only:
150189
# TODO: expand beyond 1-dimensional array support (as of writing only affects Route.swift)
151190
cloneability_lookup = current_argument_details.swift_type[1:-1].replace('Result_', 'CResult_').replace('Tuple_', 'CTuple_')
152191
array_clone_prefix = ''
@@ -157,16 +196,16 @@ def prepare_swift_to_native_arguments(cls, argument_types, is_trait_callback=Fal
157196
# array_clone_suffix = ')'
158197
pass
159198
native_call_prep += f'''
160-
let {passed_argument_name}Wrapper = Bindings.new_{current_argument_details.rust_obj}Wrapper(array: {array_clone_prefix}{passed_argument_name}{array_clone_suffix})
199+
let {argument_name}Wrapper = Bindings.new_{current_argument_details.rust_obj}Wrapper(array: {array_clone_prefix}{passed_argument_name}{array_clone_suffix})
161200
defer {{
162-
{passed_argument_name}Wrapper.noOpRetain()
201+
{argument_name}Wrapper.noOpRetain()
163202
}}
164203
'''
165204
if current_argument_details.rust_obj.startswith('LDKCVec_') or current_argument_details.rust_obj == 'LDKTransaction':
166205
# vectors will be freed by the underlying function automatically
167-
native_arguments.append(f'{passed_argument_name}Wrapper.dangle().cOpaqueStruct!')
206+
native_arguments.append(f'{argument_name}Wrapper.dangle().cOpaqueStruct!')
168207
else:
169-
native_arguments.append(f'{passed_argument_name}Wrapper.cOpaqueStruct!')
208+
native_arguments.append(f'{argument_name}Wrapper.cOpaqueStruct!')
170209
else:
171210
native_arguments.append(f'Bindings.new_{current_argument_details.rust_obj}(array: {passed_argument_name})')
172211
elif current_argument_details.rust_obj is not None and current_argument_details.rust_obj.startswith('LDK') and current_argument_details.is_unary_tuple:
@@ -197,12 +236,13 @@ def prepare_swift_to_native_arguments(cls, argument_types, is_trait_callback=Fal
197236
full_syntax = pointer_wrapping_prefix + ', '.join(native_arguments) + pointer_wrapping_suffix
198237
# print(full_syntax)
199238
return {"swift_arguments": swift_arguments, "native_arguments": native_arguments, "native_call_prefix": pointer_wrapping_prefix, "native_call_suffix": pointer_wrapping_suffix,
200-
"native_call_prep": native_call_prep, "static_eligible": static_eligible, "non_cloneable_argument_indices_passed_by_ownership": non_cloneable_argument_indices_passed_by_ownership}
239+
"native_call_prep": native_call_prep, "static_eligible": static_eligible, "non_cloneable_argument_indices_passed_by_ownership": non_cloneable_argument_indices_passed_by_ownership,
240+
'has_unwrapped_arrays': has_unwrapped_arrays, 'swift_redirection_arguments': swift_redirection_arguments}
201241

202242
# the arguments that we receive from a native lambda, before they get passed on to a human consumer
203243
# Traits -> NATIVE_CALLBACKS -> SWIFT_CALLBACK_PREP, basically
204244
@classmethod
205-
def prepare_native_to_swift_callback_arguments(cls, argument_types):
245+
def prepare_native_to_swift_callback_arguments(cls, argument_types, array_unwrapping_preparation_only=False):
206246
# let's get the current native arguments, i. e. the arguments we get from C into the native callback
207247
native_arguments = []
208248
swift_callback_arguments = []
@@ -249,7 +289,7 @@ def prepare_native_to_swift_callback_arguments(cls, argument_types):
249289
elif received_raw_type.startswith('LDKCVec') and published_swift_type.startswith('[C'):
250290
swift_local_conversion_prefix = f'Bindings.{received_raw_type}_to_array(nativeType: '
251291
swift_local_conversion_suffix = ')'
252-
if TypeParsingRegeces.WRAPPER_TYPE_ARRAY_BRACKET_REGEX.search(published_swift_type):
292+
if TypeParsingRegeces.WRAPPER_TYPE_ARRAY_BRACKET_REGEX.search(published_swift_type) and not array_unwrapping_preparation_only:
253293
# Bindings array converters cannot yet convert LDK types to wrapped types
254294
published_swift_type = TypeParsingRegeces.WRAPPER_TYPE_ARRAY_BRACKET_REGEX.sub('[LDK', published_swift_type)
255295
received_raw_type = current_argument_details.rust_obj

0 commit comments

Comments
 (0)