@@ -10,27 +10,32 @@ class ConversionHelper:
10
10
freeable_types = set ()
11
11
12
12
@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 ):
14
14
swift_arguments = []
15
+ swift_redirection_arguments = []
15
16
native_arguments = []
16
17
pointer_wrapping_prefix = ''
17
18
pointer_wrapping_suffix = ''
18
19
native_call_prep = ''
19
20
pointer_wrapping_depth = 0
20
21
static_eligible = True
21
22
non_cloneable_argument_indices_passed_by_ownership = []
23
+ has_unwrapped_arrays = False
22
24
for argument_index , current_argument_details in enumerate (argument_types ):
23
25
pass_instance = False
24
26
argument_name = current_argument_details .var_name
25
27
passed_argument_name = argument_name
26
28
is_pointer_to_array = False
29
+ is_array_wrapper_extraction_required = False
30
+ array_wrapper_extraction = ''
27
31
28
32
# if passed_argument_name == 'init': # illegal in swift
29
33
# passed_argument_name = 'initValue'
30
34
31
35
mutabilityIndicatorSuffix = ''
32
36
clone_infix = ''
33
37
cloneability_lookup = 'x-uncloneable'
38
+ individual_cloneability_lookup = None
34
39
if current_argument_details .rust_obj is not None :
35
40
cloneability_lookup = current_argument_details .rust_obj
36
41
if cloneability_lookup .startswith ('LDK' ):
@@ -45,6 +50,43 @@ def prepare_swift_to_native_arguments(cls, argument_types, is_trait_callback=Fal
45
50
passed_argument_name = 'self'
46
51
static_eligible = False
47
52
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
+
48
90
if current_argument_details .is_ptr :
49
91
passed_argument_name = argument_name + 'Pointer'
50
92
if argument_name == 'init' :
@@ -70,7 +112,7 @@ def prepare_swift_to_native_arguments(cls, argument_types, is_trait_callback=Fal
70
112
# }
71
113
# the \n\t will add a bunch of extra lines, but this file will be easier to read
72
114
73
- if requires_mutability :
115
+ if requires_mutability and not array_unwrapping_preparation_only :
74
116
if pass_instance or non_nullable :
75
117
native_call_prep += f'''
76
118
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
95
137
native_call_prep += f'''
96
138
var { passed_argument_name } : UnsafeMutablePointer<{ current_argument_details .rust_obj } >? = nil
97
139
if let { argument_name } Unwrapped = { argument_name } {{
140
+ { array_wrapper_extraction }
98
141
{ passed_argument_name } = UnsafeMutablePointer<{ current_argument_details .rust_obj } >.allocate(capacity: 1)
99
142
{ passed_argument_name } !.initialize(to: { initialization_target } )
100
143
}}
@@ -116,8 +159,7 @@ def prepare_swift_to_native_arguments(cls, argument_types, is_trait_callback=Fal
116
159
elif current_argument_details .rust_obj in ConversionHelper .trait_structs :
117
160
pass
118
161
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()'
121
163
if current_argument_details .rust_obj is not None and (
122
164
'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 (
123
165
'[' ):
@@ -129,15 +171,12 @@ def prepare_swift_to_native_arguments(cls, argument_types, is_trait_callback=Fal
129
171
if current_argument_details .swift_type .startswith ('[' ) or current_argument_details .swift_type == 'String' :
130
172
mutabilityIndicatorSuffix = '?'
131
173
132
- swift_argument_type = current_argument_details .swift_type
133
174
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_' )
140
175
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 } ' )
141
180
142
181
# native_arguments.append(f'{passed_argument_name}')
143
182
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
146
185
native_arguments .append (f'{ passed_argument_name } { clone_infix } .cOpaqueStruct!' )
147
186
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 :
148
187
# 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 :
150
189
# TODO: expand beyond 1-dimensional array support (as of writing only affects Route.swift)
151
190
cloneability_lookup = current_argument_details .swift_type [1 :- 1 ].replace ('Result_' , 'CResult_' ).replace ('Tuple_' , 'CTuple_' )
152
191
array_clone_prefix = ''
@@ -157,16 +196,16 @@ def prepare_swift_to_native_arguments(cls, argument_types, is_trait_callback=Fal
157
196
# array_clone_suffix = ')'
158
197
pass
159
198
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 } )
161
200
defer {{
162
- { passed_argument_name } Wrapper.noOpRetain()
201
+ { argument_name } Wrapper.noOpRetain()
163
202
}}
164
203
'''
165
204
if current_argument_details .rust_obj .startswith ('LDKCVec_' ) or current_argument_details .rust_obj == 'LDKTransaction' :
166
205
# 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!' )
168
207
else :
169
- native_arguments .append (f'{ passed_argument_name } Wrapper.cOpaqueStruct!' )
208
+ native_arguments .append (f'{ argument_name } Wrapper.cOpaqueStruct!' )
170
209
else :
171
210
native_arguments .append (f'Bindings.new_{ current_argument_details .rust_obj } (array: { passed_argument_name } )' )
172
211
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
197
236
full_syntax = pointer_wrapping_prefix + ', ' .join (native_arguments ) + pointer_wrapping_suffix
198
237
# print(full_syntax)
199
238
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 }
201
241
202
242
# the arguments that we receive from a native lambda, before they get passed on to a human consumer
203
243
# Traits -> NATIVE_CALLBACKS -> SWIFT_CALLBACK_PREP, basically
204
244
@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 ):
206
246
# let's get the current native arguments, i. e. the arguments we get from C into the native callback
207
247
native_arguments = []
208
248
swift_callback_arguments = []
@@ -249,7 +289,7 @@ def prepare_native_to_swift_callback_arguments(cls, argument_types):
249
289
elif received_raw_type .startswith ('LDKCVec' ) and published_swift_type .startswith ('[C' ):
250
290
swift_local_conversion_prefix = f'Bindings.{ received_raw_type } _to_array(nativeType: '
251
291
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 :
253
293
# Bindings array converters cannot yet convert LDK types to wrapped types
254
294
published_swift_type = TypeParsingRegeces .WRAPPER_TYPE_ARRAY_BRACKET_REGEX .sub ('[LDK' , published_swift_type )
255
295
received_raw_type = current_argument_details .rust_obj
0 commit comments