@@ -13,29 +13,121 @@ public class MethodDetailsCache
13
13
public string RawName ;
14
14
public string [ ] InputParameterNames ;
15
15
public Tuple < TypeReference , InputKind > [ ] InputParameterTypes ;
16
- public TypeReference [ ] OutTypes ;
17
- public string WrapperBody ;
16
+ public Tuple < TypeReference , bool > [ ] OutTypes ;
17
+ public string GetManyParameterName ;
18
+ public List < Tuple < string , TypeReference , bool > > Output ;
18
19
19
20
public string [ ] MakeInputParameters ( Generator generator , ITypeRequestSource source )
20
21
{
21
22
return InputParameterNames . Zip ( InputParameterTypes , ( name , t ) => name + ": " + TypeHelpers . GetInputTypeName ( generator , source , t . Item1 , t . Item2 ) ) . ToArray ( ) ;
22
23
}
23
24
24
- public string MakeOutType ( Generator generator , ITypeRequestSource source )
25
+ public string MakeOutType ( Generator generator , ITypeRequestSource source , bool isFactoryMethod )
25
26
{
26
- string outType = String . Join ( ", " , OutTypes . Select ( o => TypeHelpers . GetTypeName ( generator , source , o , TypeUsage . Out ) ) ) ;
27
+ string outType = String . Join ( ", " , OutTypes . Select ( o => TypeHelpers . GetTypeName ( generator , source , o . Item1 , ( o . Item2 || isFactoryMethod ) ? TypeUsage . OutNonNull : TypeUsage . Out ) ) ) ;
27
28
if ( OutTypes . Count ( ) != 1 )
28
29
{
29
30
outType = "(" + outType + ")" ; // also works for count == 0 (empty tuple)
30
31
}
31
32
return outType ;
32
33
}
34
+
35
+ public string MakeWrapperBody ( MethodDefinition def , bool isFactoryMethod )
36
+ {
37
+ var rawName = RawName ;
38
+ bool isGetMany = GetManyParameterName != null ;
39
+ var getManyPname = GetManyParameterName ;
40
+ var output = Output ;
41
+
42
+ var rawParams = new List < string > { "self as *const _ as *mut _" } ;
43
+ foreach ( var p in def . Parameters )
44
+ {
45
+ var pname = NameHelpers . PreventKeywords ( NameHelpers . FirstToLower ( p . Name ) ) ;
46
+ if ( p . ParameterType . IsByReference )
47
+ {
48
+ if ( ( ( ByReferenceType ) p . ParameterType ) . ElementType . IsArray )
49
+ {
50
+ rawParams . Add ( "&mut " + pname + "Size" ) ;
51
+ }
52
+
53
+ // output parameter
54
+ rawParams . Add ( "&mut " + pname ) ;
55
+ }
56
+ else
57
+ {
58
+ // input parameter
59
+ if ( p . ParameterType . IsArray )
60
+ {
61
+ if ( p . IsOut )
62
+ {
63
+ if ( isGetMany )
64
+ {
65
+ rawParams . Add ( pname + ".capacity() as u32" ) ;
66
+ rawParams . Add ( pname + ".as_mut_ptr() as *mut T::Abi" ) ;
67
+ }
68
+ else
69
+ {
70
+ rawParams . Add ( pname + ".len() as u32" ) ;
71
+ rawParams . Add ( pname + ".as_mut_ptr() as *mut _" ) ;
72
+ }
73
+ }
74
+ else
75
+ {
76
+ rawParams . Add ( pname + ".len() as u32" ) ;
77
+ rawParams . Add ( pname + ".as_ptr() as *mut _" ) ;
78
+ }
79
+ }
80
+ else
81
+ {
82
+ rawParams . Add ( TypeHelpers . UnwrapInputParameter ( pname , p . ParameterType ) ) ;
83
+ }
84
+ }
85
+ }
86
+
87
+ if ( def . ReturnType . FullName != "System.Void" )
88
+ {
89
+ if ( def . ReturnType . IsArray )
90
+ {
91
+ rawParams . Add ( "&mut outSize" ) ;
92
+ }
93
+ rawParams . Add ( "&mut out" ) ;
94
+ }
95
+
96
+ var outInit = String . Join ( " " , output . SelectMany ( o => TypeHelpers . CreateUninitializedOutputs ( o . Item1 , o . Item2 ) ) ) ;
97
+ if ( outInit != "" ) outInit = "\r \n " + outInit ;
98
+
99
+ var outWrap = String . Join ( ", " , output . Select ( o => TypeHelpers . WrapOutputParameter ( o . Item1 , o . Item2 , isFactoryMethod || o . Item3 ) ) ) ;
100
+ if ( output . Count != 1 )
101
+ {
102
+ outWrap = "(" + outWrap + ")" ; // also works for count == 0 (empty tuple)
103
+ }
104
+ outWrap = "Ok(" + outWrap + ")" ;
105
+
106
+ if ( isGetMany )
107
+ {
108
+ outInit = $ "\r \n debug_assert!({ getManyPname } .capacity() > 0, \" capacity of `{ getManyPname } ` must not be 0 (use Vec::with_capacity)\" ); { getManyPname } .clear();{ outInit } ";
109
+ outWrap = $ "{ getManyPname } .set_len(out as usize); Ok(())";
110
+ }
111
+
112
+ return outInit + $@ "
113
+ let hr = ((*self.lpVtbl).{ rawName } )({ String . Join ( ", " , rawParams ) } );
114
+ if hr == S_OK {{ { outWrap } }} else {{ err(hr) }}" ;
115
+ }
33
116
}
34
117
35
118
public class MethodDef : ITypeRequestSource
36
119
{
37
120
public TypeDef DeclaringType { get ; private set ; }
38
121
public MethodDefinition Method { get ; private set ; }
122
+ public bool IsFactoryMethod
123
+ {
124
+ get
125
+ {
126
+ var kind = ( ( InterfaceDef ) DeclaringType ) . InterfaceKind ;
127
+ if ( kind == InterfaceKind . Unidentified ) { throw new InvalidOperationException ( ) ; }
128
+ return kind == InterfaceKind . Factory ;
129
+ }
130
+ }
39
131
40
132
public Module Module
41
133
{
@@ -120,10 +212,10 @@ public string GetWrapperName(string rawName)
120
212
public string GetWrapperDefinition ( )
121
213
{
122
214
var inputParameters = Details . MakeInputParameters ( DeclaringType . Generator , this ) ;
123
- var outType = Details . MakeOutType ( DeclaringType . Generator , this ) ;
215
+ var outType = Details . MakeOutType ( DeclaringType . Generator , this , IsFactoryMethod ) ;
124
216
125
- return $@ "#[inline] pub unsafe fn { Details . WrappedName } ({ String . Join ( ", " , new string [ ] { "&self" } . Concat ( inputParameters ) ) } ) -> Result<{ outType } > {{{ Details.WrapperBody }
126
- }}" ;
217
+ return $@ "#[inline] pub fn { Details . WrappedName } ({ String . Join ( ", " , new string [ ] { "&self" } . Concat ( inputParameters ) ) } ) -> Result<{ outType } > {{ unsafe {{ { Details . MakeWrapperBody ( Method , IsFactoryMethod ) }
218
+ }}}} " ;
127
219
}
128
220
129
221
private MethodDetailsCache InitializeDetailsCache ( )
@@ -139,7 +231,7 @@ private MethodDetailsCache InitializeDetailsCache()
139
231
// It uses the __RPC__out_ecount_part(capacity, *actual) annotation in the C headers. For the wrapper we use a &mut Vec<> buffer.
140
232
141
233
var input = new List < Tuple < string , TypeReference , InputKind > > ( ) ;
142
- var output = new List < Tuple < string , TypeReference > > ( ) ;
234
+ var output = new List < Tuple < string , TypeReference , bool > > ( ) ;
143
235
144
236
foreach ( var p in Method . Parameters )
145
237
{
@@ -148,7 +240,7 @@ private MethodDetailsCache InitializeDetailsCache()
148
240
{
149
241
Assert ( p . IsOut ) ;
150
242
var realType = ( ( ByReferenceType ) p . ParameterType ) . ElementType ;
151
- output . Add ( Tuple . Create ( pname , realType ) ) ;
243
+ output . Add ( Tuple . Create ( pname , realType , false ) ) ;
152
244
}
153
245
else
154
246
{
@@ -182,17 +274,18 @@ private MethodDetailsCache InitializeDetailsCache()
182
274
if ( Method . ReturnType . FullName != "System.Void" )
183
275
{
184
276
// this makes the actual return value the last in the tuple (if multiple)
185
- output . Add ( Tuple . Create ( "out" , Method . ReturnType ) ) ;
277
+ output . Add ( Tuple . Create ( "out" , Method . ReturnType , TypeHelpers . IsReturnTypeNonNull ( Method . ReturnType , DeclaringType . Generator ) ) ) ;
186
278
}
187
279
188
- var outTypes = output . Select ( o => o . Item2 ) . ToArray ( ) ;
280
+ // TODO: second tuple element should be true for some method's return value
281
+ var outTypes = output . Select ( o => Tuple . Create ( o . Item2 , o . Item3 ) ) . ToArray ( ) ;
189
282
190
283
if ( isGetMany )
191
284
{
192
- outTypes = new TypeReference [ ] { } ; // GetMany has no return value
285
+ outTypes = new Tuple < TypeReference , bool > [ ] { } ; // GetMany has no return value
193
286
}
194
287
195
-
288
+
196
289
197
290
return new MethodDetailsCache
198
291
{
@@ -201,87 +294,11 @@ private MethodDetailsCache InitializeDetailsCache()
201
294
InputParameterNames = input . Select ( i => i . Item1 ) . ToArray ( ) ,
202
295
InputParameterTypes = input . Select ( i => Tuple . Create ( i . Item2 , i . Item3 ) ) . ToArray ( ) ,
203
296
OutTypes = outTypes . ToArray ( ) ,
204
- WrapperBody = GetWrapperBody ( rawName , isGetMany , getManyPname , output )
297
+ GetManyParameterName = isGetMany ? getManyPname : null ,
298
+ Output = output
205
299
} ;
206
300
}
207
301
208
- private string GetWrapperBody ( string rawName , bool isGetMany , string getManyPname , List < Tuple < string , TypeReference > > output )
209
- {
210
- var rawParams = new List < string > { "self as *const _ as *mut _" } ;
211
- foreach ( var p in Method . Parameters )
212
- {
213
- var pname = NameHelpers . PreventKeywords ( NameHelpers . FirstToLower ( p . Name ) ) ;
214
- if ( p . ParameterType . IsByReference )
215
- {
216
- if ( ( ( ByReferenceType ) p . ParameterType ) . ElementType . IsArray )
217
- {
218
- rawParams . Add ( "&mut " + pname + "Size" ) ;
219
- }
220
-
221
- // output parameter
222
- rawParams . Add ( "&mut " + pname ) ;
223
- }
224
- else
225
- {
226
- // input parameter
227
- if ( p . ParameterType . IsArray )
228
- {
229
- if ( p . IsOut )
230
- {
231
- if ( isGetMany )
232
- {
233
- rawParams . Add ( pname + ".capacity() as u32" ) ;
234
- rawParams . Add ( pname + ".as_mut_ptr() as *mut T::Abi" ) ;
235
- }
236
- else
237
- {
238
- rawParams . Add ( pname + ".len() as u32" ) ;
239
- rawParams . Add ( pname + ".as_mut_ptr() as *mut _" ) ;
240
- }
241
- }
242
- else
243
- {
244
- rawParams . Add ( pname + ".len() as u32" ) ;
245
- rawParams . Add ( pname + ".as_ptr() as *mut _" ) ;
246
- }
247
- }
248
- else
249
- {
250
- rawParams . Add ( TypeHelpers . UnwrapInputParameter ( pname , p . ParameterType ) ) ;
251
- }
252
- }
253
- }
254
-
255
- if ( Method . ReturnType . FullName != "System.Void" )
256
- {
257
- if ( Method . ReturnType . IsArray )
258
- {
259
- rawParams . Add ( "&mut outSize" ) ;
260
- }
261
- rawParams . Add ( "&mut out" ) ;
262
- }
263
-
264
- var outInit = String . Join ( " " , output . SelectMany ( o => TypeHelpers . CreateUninitializedOutputs ( o . Item1 , o . Item2 ) ) ) ;
265
- if ( outInit != "" ) outInit = "\r \n " + outInit ;
266
-
267
- var outWrap = String . Join ( ", " , output . Select ( o => TypeHelpers . WrapOutputParameter ( o . Item1 , o . Item2 ) ) ) ;
268
- if ( output . Count != 1 )
269
- {
270
- outWrap = "(" + outWrap + ")" ; // also works for count == 0 (empty tuple)
271
- }
272
- outWrap = "Ok(" + outWrap + ")" ;
273
-
274
- if ( isGetMany )
275
- {
276
- outInit = $ "\r \n debug_assert!({ getManyPname } .capacity() > 0, \" capacity of `{ getManyPname } ` must not be 0 (use Vec::with_capacity)\" ); { getManyPname } .clear();{ outInit } ";
277
- outWrap = $ "{ getManyPname } .set_len(out as usize); Ok(())";
278
- }
279
-
280
- return outInit + $@ "
281
- let hr = ((*self.lpVtbl).{ rawName } )({ String . Join ( ", " , rawParams ) } );
282
- if hr == S_OK {{ { outWrap } }} else {{ err(hr) }}" ;
283
- }
284
-
285
302
public string GetRawDeclaration ( )
286
303
{
287
304
var name = GetRawName ( ) ;
0 commit comments