@@ -192,7 +192,74 @@ impl<'a, 'b> Js2Rust<'a, 'b> {
192
192
}
193
193
194
194
if optional {
195
- bail ! ( "unsupported optional argument to rust function {:?}" , arg) ;
195
+ if arg. is_primitive ( ) {
196
+ self . cx . expose_is_like_none ( ) ;
197
+ self . js_arguments . push ( ( name. clone ( ) , "number" . to_string ( ) ) ) ;
198
+
199
+ if self . cx . config . debug {
200
+ self . cx . expose_assert_num ( ) ;
201
+ self . prelude ( & format ! (
202
+ "\n \
203
+ if (!isLikeNone({0})) {{\n \
204
+ _assertNum({0});\n \
205
+ }}\n \
206
+ ",
207
+ name
208
+ ) ) ;
209
+ }
210
+
211
+ self . rust_arguments . push ( format ! ( "!isLikeNone({0})" , name) ) ;
212
+ self . rust_arguments . push ( format ! ( "isLikeNone({0}) ? 0 : {0}" , name) ) ;
213
+ return Ok ( self ) ;
214
+ }
215
+
216
+ if arg. is_as_u32 ( ) {
217
+ self . cx . expose_is_like_none ( ) ;
218
+ self . js_arguments . push ( ( name. clone ( ) , "number" . to_string ( ) ) ) ;
219
+
220
+ if self . cx . config . debug {
221
+ self . cx . expose_assert_num ( ) ;
222
+ self . prelude ( & format ! (
223
+ "\n \
224
+ if (!isLikeNone({0})) {{\n \
225
+ _assertNum({0});\n \
226
+ }}\n \
227
+ ",
228
+ name
229
+ ) ) ;
230
+ }
231
+
232
+ self . rust_arguments . push ( format ! ( "isLikeNone({0}) ? 0xFFFFFF : {0}" , name) ) ;
233
+ return Ok ( self ) ;
234
+ }
235
+
236
+ if let Some ( signed) = arg. get_64 ( ) {
237
+ let f = if signed {
238
+ self . cx . expose_int64_cvt_shim ( )
239
+ } else {
240
+ self . cx . expose_uint64_cvt_shim ( )
241
+ } ;
242
+ self . cx . expose_uint32_memory ( ) ;
243
+ self . cx . expose_global_argument_ptr ( ) ?;
244
+ self . js_arguments . push ( ( name. clone ( ) , "BigInt" . to_string ( ) ) ) ;
245
+ self . prelude ( & format ! (
246
+ "\
247
+ {f}[0] = isLikeNone({name}) ? BigInt(0) : {name};\n \
248
+ const low{i} = isLikeNone({name}) ? 0 : u32CvtShim[0];\n \
249
+ const high{i} = isLikeNone({name}) ? 0 : u32CvtShim[1];\n \
250
+ ",
251
+ i = i,
252
+ f = f,
253
+ name = name,
254
+ ) ) ;
255
+ self . rust_arguments . push ( format ! ( "!isLikeNone({})" , name) ) ;
256
+ self . rust_arguments . push ( format ! ( "0" ) ) ;
257
+ self . rust_arguments . push ( format ! ( "low{}" , i) ) ;
258
+ self . rust_arguments . push ( format ! ( "high{}" , i) ) ;
259
+ return Ok ( self ) ;
260
+ }
261
+
262
+ bail ! ( "unsupported optional argument type for calling Rust function from JS: {:?}" , arg) ;
196
263
}
197
264
198
265
if let Some ( s) = arg. rust_struct ( ) {
@@ -240,7 +307,7 @@ impl<'a, 'b> Js2Rust<'a, 'b> {
240
307
return Ok ( self ) ;
241
308
}
242
309
243
- if let Some ( signed) = arg. get_64bit ( ) {
310
+ if let Some ( signed) = arg. get_64 ( ) {
244
311
let f = if signed {
245
312
self . cx . expose_int64_cvt_shim ( )
246
313
} else {
@@ -252,15 +319,15 @@ impl<'a, 'b> Js2Rust<'a, 'b> {
252
319
self . prelude ( & format ! (
253
320
"\
254
321
{f}[0] = {name};\n \
255
- const lo {i} = u32CvtShim[0];\n \
256
- const hi {i} = u32CvtShim[1];\n \
322
+ const low {i} = u32CvtShim[0];\n \
323
+ const high {i} = u32CvtShim[1];\n \
257
324
",
258
325
i = i,
259
326
f = f,
260
327
name = name,
261
328
) ) ;
262
- self . rust_arguments . push ( format ! ( "lo {}" , i) ) ;
263
- self . rust_arguments . push ( format ! ( "hi {}" , i) ) ;
329
+ self . rust_arguments . push ( format ! ( "low {}" , i) ) ;
330
+ self . rust_arguments . push ( format ! ( "high {}" , i) ) ;
264
331
return Ok ( self ) ;
265
332
}
266
333
@@ -292,7 +359,7 @@ impl<'a, 'b> Js2Rust<'a, 'b> {
292
359
self . js_arguments . push ( ( name. clone ( ) , "string" . to_string ( ) ) ) ;
293
360
self . rust_arguments . push ( format ! ( "{}.codePointAt(0)" , name) )
294
361
}
295
- _ => bail ! ( "unsupported argument to rust function {:?}" , arg) ,
362
+ _ => bail ! ( "unsupported argument type for calling Rust function from JS: {:?}" , arg) ,
296
363
}
297
364
Ok ( self )
298
365
}
@@ -348,7 +415,78 @@ impl<'a, 'b> Js2Rust<'a, 'b> {
348
415
}
349
416
350
417
if optional {
351
- bail ! ( "unsupported optional argument to rust function {:?}" , ty) ;
418
+ if ty. is_primitive ( ) {
419
+ self . ret_ty = "number" . to_string ( ) ;
420
+ self . cx . expose_global_argument_ptr ( ) ?;
421
+ self . cx . expose_uint32_memory ( ) ;
422
+ match ty {
423
+ Descriptor :: I32 => self . cx . expose_int32_memory ( ) ,
424
+ Descriptor :: U32 => ( ) ,
425
+ Descriptor :: F32 => self . cx . expose_f32_memory ( ) ,
426
+ Descriptor :: F64 => self . cx . expose_f64_memory ( ) ,
427
+ _ => ( ) ,
428
+ } ;
429
+ self . prelude ( "const retptr = globalArgumentPtr();" ) ;
430
+ self . rust_arguments . insert ( 0 , "retptr" . to_string ( ) ) ;
431
+ self . ret_expr = format ! (
432
+ "\
433
+ RET;\n \
434
+ const present = getUint32Memory()[retptr / 4];\n \
435
+ const value = {mem}[retptr / {size} + 1];\n \
436
+ return present === 0 ? undefined : value;\n \
437
+ ",
438
+ size = match ty {
439
+ Descriptor :: I32 => 4 ,
440
+ Descriptor :: U32 => 4 ,
441
+ Descriptor :: F32 => 4 ,
442
+ Descriptor :: F64 => 8 ,
443
+ _ => unreachable!( ) ,
444
+ } ,
445
+ mem = match ty {
446
+ Descriptor :: I32 => "getInt32Memory()" ,
447
+ Descriptor :: U32 => "getUint32Memory()" ,
448
+ Descriptor :: F32 => "getFloat32Memory()" ,
449
+ Descriptor :: F64 => "getFloat64Memory()" ,
450
+ _ => unreachable!( ) ,
451
+ }
452
+ ) ;
453
+ return Ok ( self ) ;
454
+ }
455
+
456
+ if ty. is_as_u32 ( ) {
457
+ self . ret_ty = "number" . to_string ( ) ;
458
+ self . ret_expr = "
459
+ const ret = RET;
460
+ return ret === 0xFFFFFF ? undefined : ret;
461
+ " . to_string ( ) ;
462
+ return Ok ( self ) ;
463
+ }
464
+
465
+ if let Some ( signed) = ty. get_64 ( ) {
466
+ self . ret_ty = "BigInt" . to_string ( ) ;
467
+ self . cx . expose_global_argument_ptr ( ) ?;
468
+ let f = if signed {
469
+ self . cx . expose_int64_memory ( ) ;
470
+ "getInt64Memory"
471
+ } else {
472
+ self . cx . expose_uint64_memory ( ) ;
473
+ "getUint64Memory"
474
+ } ;
475
+ self . prelude ( "const retptr = globalArgumentPtr();" ) ;
476
+ self . rust_arguments . insert ( 0 , "retptr" . to_string ( ) ) ;
477
+ self . ret_expr = format ! (
478
+ "\
479
+ RET;\n \
480
+ const present = getUint32Memory()[retptr / 4];\n \
481
+ const value = {}()[retptr / 8 + 1];\n \
482
+ return present === 0 ? undefined : value;\n \
483
+ ",
484
+ f
485
+ ) ;
486
+ return Ok ( self ) ;
487
+ }
488
+
489
+ bail ! ( "unsupported optional return type for calling Rust function from JS: {:?}" , ty) ;
352
490
}
353
491
354
492
if ty. is_ref_anyref ( ) {
@@ -374,7 +512,7 @@ impl<'a, 'b> Js2Rust<'a, 'b> {
374
512
return Ok ( self ) ;
375
513
}
376
514
377
- if let Some ( signed) = ty. get_64bit ( ) {
515
+ if let Some ( signed) = ty. get_64 ( ) {
378
516
self . ret_ty = "BigInt" . to_string ( ) ;
379
517
self . cx . expose_global_argument_ptr ( ) ?;
380
518
let f = if signed {
@@ -405,7 +543,7 @@ impl<'a, 'b> Js2Rust<'a, 'b> {
405
543
self . ret_ty = "string" . to_string ( ) ;
406
544
self . ret_expr = format ! ( "return String.fromCodePoint(RET);" )
407
545
}
408
- _ => bail ! ( "unsupported return from Rust to JS {:?}" , ty) ,
546
+ _ => bail ! ( "unsupported return type for calling Rust function from JS: {:?}" , ty) ,
409
547
}
410
548
Ok ( self )
411
549
}
0 commit comments