@@ -461,7 +461,7 @@ impl WorldGenerator for CSharp {
461
461
{access} readonly struct None {{}}
462
462
463
463
[StructLayout(LayoutKind.Sequential)]
464
- {access} readonly struct Result<Ok, Err >
464
+ {access} readonly struct Result<TOk, TErr >
465
465
{{
466
466
{access} readonly byte Tag;
467
467
private readonly object value;
@@ -472,43 +472,50 @@ impl WorldGenerator for CSharp {
472
472
this.value = value;
473
473
}}
474
474
475
- {access} static Result<Ok, Err> ok(Ok ok)
475
+ {access} static Result<TOk, TErr> Ok(TOk ok)
476
476
{{
477
- return new Result<Ok, Err>(OK , ok!);
477
+ return new Result<TOk, TErr>(Tags.Ok , ok!);
478
478
}}
479
479
480
- {access} static Result<Ok, Err> err( Err err)
480
+ {access} static Result<TOk, TErr> Err(TErr err)
481
481
{{
482
- return new Result<Ok, Err>(ERR , err!);
482
+ return new Result<TOk, TErr>(Tags.Err , err!);
483
483
}}
484
484
485
- {access} bool IsOk => Tag == OK ;
486
- {access} bool IsErr => Tag == ERR ;
485
+ {access} bool IsOk => Tag == Tags.Ok ;
486
+ {access} bool IsErr => Tag == Tags.Err ;
487
487
488
- {access} Ok AsOk
488
+ {access} TOk AsOk
489
489
{{
490
490
get
491
491
{{
492
- if (Tag == OK)
493
- return (Ok)value;
494
- else
495
- throw new ArgumentException("expected OK, got " + Tag);
492
+ if (Tag == Tags.Ok)
493
+ {{
494
+ return (TOk)value;
495
+ }}
496
+
497
+ throw new ArgumentException("expected k, got " + Tag);
496
498
}}
497
499
}}
498
500
499
- {access} Err AsErr
501
+ {access} TErr AsErr
500
502
{{
501
503
get
502
504
{{
503
- if (Tag == ERR)
504
- return (Err)value;
505
- else
506
- throw new ArgumentException("expected ERR, got " + Tag);
505
+ if (Tag == Tags.Err)
506
+ {{
507
+ return (TErr)value;
508
+ }}
509
+
510
+ throw new ArgumentException("expected Err, got " + Tag);
507
511
}}
508
512
}}
509
513
510
- {access} const byte OK = 0;
511
- {access} const byte ERR = 1;
514
+ {access} class Tags
515
+ {{
516
+ {access} const byte Ok = 0;
517
+ {access} const byte Err = 1;
518
+ }}
512
519
}}
513
520
"# ,
514
521
)
@@ -1144,6 +1151,8 @@ impl InterfaceGenerator<'_> {
1144
1151
1145
1152
let import_name = & func. name ;
1146
1153
1154
+ self . gen . require_using ( "System.Runtime.InteropServices" ) ;
1155
+
1147
1156
let target = if let FunctionKind :: Freestanding = & func. kind {
1148
1157
self . require_interop_using ( "System.Runtime.InteropServices" ) ;
1149
1158
& mut self . csharp_interop_src
@@ -1865,7 +1874,7 @@ impl<'a> wit_bindgen_core::InterfaceGenerator<'a> for InterfaceGenerator<'a> {
1865
1874
. iter ( )
1866
1875
. map ( |case| {
1867
1876
let case_name = case. name . to_csharp_ident ( ) ;
1868
- let tag = case. name . to_shouty_snake_case ( ) ;
1877
+ let tag = case. name . to_csharp_ident_upper ( ) ;
1869
1878
let ( parameter, argument) = if let Some ( ty) = self . non_empty_type ( case. ty . as_ref ( ) )
1870
1879
{
1871
1880
(
@@ -1877,8 +1886,8 @@ impl<'a> wit_bindgen_core::InterfaceGenerator<'a> for InterfaceGenerator<'a> {
1877
1886
} ;
1878
1887
1879
1888
format ! (
1880
- "{access} static {name} {case_name }({parameter}) {{
1881
- return new {name}({tag}, {argument});
1889
+ "{access} static {name} {tag }({parameter}) {{
1890
+ return new {name}(Tags. {tag}, {argument});
1882
1891
}}
1883
1892
"
1884
1893
)
@@ -1892,14 +1901,14 @@ impl<'a> wit_bindgen_core::InterfaceGenerator<'a> for InterfaceGenerator<'a> {
1892
1901
. filter_map ( |case| {
1893
1902
self . non_empty_type ( case. ty . as_ref ( ) ) . map ( |ty| {
1894
1903
let case_name = case. name . to_upper_camel_case ( ) ;
1895
- let tag = case. name . to_shouty_snake_case ( ) ;
1904
+ let tag = case. name . to_csharp_ident_upper ( ) ;
1896
1905
let ty = self . type_name ( ty) ;
1897
1906
format ! (
1898
1907
r#"{access} {ty} As{case_name}
1899
1908
{{
1900
1909
get
1901
1910
{{
1902
- if (Tag == {tag})
1911
+ if (Tag == Tags. {tag})
1903
1912
return ({ty})value!;
1904
1913
else
1905
1914
throw new ArgumentException("expected {tag}, got " + Tag);
@@ -1917,7 +1926,7 @@ impl<'a> wit_bindgen_core::InterfaceGenerator<'a> for InterfaceGenerator<'a> {
1917
1926
. iter ( )
1918
1927
. enumerate ( )
1919
1928
. map ( |( i, case) | {
1920
- let tag = case. name . to_shouty_snake_case ( ) ;
1929
+ let tag = case. name . to_csharp_ident_upper ( ) ;
1921
1930
format ! ( "{access} const {tag_type} {tag} = {i};" )
1922
1931
} )
1923
1932
. collect :: < Vec < _ > > ( )
@@ -1937,7 +1946,10 @@ impl<'a> wit_bindgen_core::InterfaceGenerator<'a> for InterfaceGenerator<'a> {
1937
1946
1938
1947
{constructors}
1939
1948
{accessors}
1940
- {tags}
1949
+
1950
+ {access} class Tags {{
1951
+ {tags}
1952
+ }}
1941
1953
}}
1942
1954
"
1943
1955
) ;
@@ -2195,7 +2207,7 @@ impl<'a, 'b> FunctionBindgen<'a, 'b> {
2195
2207
String :: new ( )
2196
2208
} ;
2197
2209
2198
- let method = case_name. to_csharp_ident ( ) ;
2210
+ let method = case_name. to_csharp_ident_upper ( ) ;
2199
2211
2200
2212
let call = if let Some ( position) = generics_position {
2201
2213
let ( ty, generics) = ty. split_at ( position) ;
@@ -2557,15 +2569,15 @@ impl Bindgen for FunctionBindgen<'_, '_> {
2557
2569
result,
2558
2570
..
2559
2571
} => self . lower_variant (
2560
- & [ ( "ok " , result. ok ) , ( "err " , result. err ) ] ,
2572
+ & [ ( "Ok " , result. ok ) , ( "Err " , result. err ) ] ,
2561
2573
lowered_types,
2562
2574
& operands[ 0 ] ,
2563
2575
results,
2564
2576
) ,
2565
2577
2566
2578
Instruction :: ResultLift { result, ty } => self . lift_variant (
2567
2579
& Type :: Id ( * ty) ,
2568
- & [ ( "ok " , result. ok ) , ( "err " , result. err ) ] ,
2580
+ & [ ( "Ok " , result. ok ) , ( "Err " , result. err ) ] ,
2569
2581
& operands[ 0 ] ,
2570
2582
results,
2571
2583
) ,
@@ -2844,13 +2856,13 @@ impl Bindgen for FunctionBindgen<'_, '_> {
2844
2856
format ! (
2845
2857
"\
2846
2858
case {index}: {{
2847
- ret = {head}{ty}.err (({err_ty}) e.Value){tail};
2859
+ ret = {head}{ty}.Err (({err_ty}) e.Value){tail};
2848
2860
break;
2849
2861
}}
2850
2862
"
2851
2863
)
2852
2864
) ;
2853
- oks. push ( format ! ( "{ty}.ok (" ) ) ;
2865
+ oks. push ( format ! ( "{ty}.Ok (" ) ) ;
2854
2866
payload_is_void = result. ok . is_none ( ) ;
2855
2867
}
2856
2868
if !self . results . is_empty ( ) {
@@ -3382,28 +3394,110 @@ fn is_primitive(ty: &Type) -> bool {
3382
3394
}
3383
3395
3384
3396
trait ToCSharpIdent : ToOwned {
3397
+ fn csharp_keywords ( ) -> Vec < & ' static str > ;
3385
3398
fn to_csharp_ident ( & self ) -> Self :: Owned ;
3399
+ fn to_csharp_ident_upper ( & self ) -> Self :: Owned ;
3386
3400
}
3387
3401
3388
3402
impl ToCSharpIdent for str {
3403
+ // Source: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/
3404
+ fn csharp_keywords ( ) -> Vec < & ' static str > {
3405
+ vec ! [
3406
+ "abstract" ,
3407
+ "as" ,
3408
+ "base" ,
3409
+ "bool" ,
3410
+ "break" ,
3411
+ "byte" ,
3412
+ "case" ,
3413
+ "catch" ,
3414
+ "char" ,
3415
+ "checked" ,
3416
+ "class" ,
3417
+ "const" ,
3418
+ "continue" ,
3419
+ "decimal" ,
3420
+ "default" ,
3421
+ "delegate" ,
3422
+ "do" ,
3423
+ "double" ,
3424
+ "else" ,
3425
+ "enum" ,
3426
+ "event" ,
3427
+ "explicit" ,
3428
+ "extern" ,
3429
+ "false" ,
3430
+ "finally" ,
3431
+ "fixed" ,
3432
+ "float" ,
3433
+ "for" ,
3434
+ "foreach" ,
3435
+ "goto" ,
3436
+ "if" ,
3437
+ "implicit" ,
3438
+ "in" ,
3439
+ "int" ,
3440
+ "interface" ,
3441
+ "internal" ,
3442
+ "is" ,
3443
+ "lock" ,
3444
+ "long" ,
3445
+ "namespace" ,
3446
+ "new" ,
3447
+ "null" ,
3448
+ "object" ,
3449
+ "operator" ,
3450
+ "out" ,
3451
+ "override" ,
3452
+ "params" ,
3453
+ "private" ,
3454
+ "protected" ,
3455
+ "public" ,
3456
+ "readonly" ,
3457
+ "ref" ,
3458
+ "return" ,
3459
+ "sbyte" ,
3460
+ "sealed" ,
3461
+ "short" ,
3462
+ "sizeof" ,
3463
+ "stackalloc" ,
3464
+ "static" ,
3465
+ "string" ,
3466
+ "struct" ,
3467
+ "switch" ,
3468
+ "this" ,
3469
+ "throw" ,
3470
+ "true" ,
3471
+ "try" ,
3472
+ "typeof" ,
3473
+ "uint" ,
3474
+ "ulong" ,
3475
+ "unchecked" ,
3476
+ "unsafe" ,
3477
+ "ushort" ,
3478
+ "using" ,
3479
+ "virtual" ,
3480
+ "void" ,
3481
+ "volatile" ,
3482
+ "while" ,
3483
+ ]
3484
+ }
3485
+
3389
3486
fn to_csharp_ident ( & self ) -> String {
3390
3487
// Escape C# keywords
3391
- // Source: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/
3392
-
3393
- //TODO: Repace with actual keywords
3394
- match self {
3395
- "abstract" | "as" | "base" | "bool" | "break" | "byte" | "case" | "catch" | "char"
3396
- | "checked" | "class" | "const" | "continue" | "decimal" | "default" | "delegate"
3397
- | "do" | "double" | "else" | "enum" | "event" | "explicit" | "extern" | "false"
3398
- | "finally" | "fixed" | "float" | "for" | "foreach" | "goto" | "if" | "implicit"
3399
- | "in" | "int" | "interface" | "internal" | "is" | "lock" | "long" | "namespace"
3400
- | "new" | "null" | "object" | "operator" | "out" | "override" | "params"
3401
- | "private" | "protected" | "public" | "readonly" | "ref" | "return" | "sbyte"
3402
- | "sealed" | "short" | "sizeof" | "stackalloc" | "static" | "string" | "struct"
3403
- | "switch" | "this" | "throw" | "true" | "try" | "typeof" | "uint" | "ulong"
3404
- | "unchecked" | "unsafe" | "ushort" | "using" | "virtual" | "void" | "volatile"
3405
- | "while" => format ! ( "@{self}" ) ,
3406
- _ => self . to_lower_camel_case ( ) ,
3488
+ if Self :: csharp_keywords ( ) . contains ( & self ) {
3489
+ format ! ( "@{}" , self )
3490
+ } else {
3491
+ self . to_lower_camel_case ( )
3492
+ }
3493
+ }
3494
+
3495
+ fn to_csharp_ident_upper ( & self ) -> String {
3496
+ // Escape C# keywords
3497
+ if Self :: csharp_keywords ( ) . contains ( & self ) {
3498
+ format ! ( "@{}" , self )
3499
+ } else {
3500
+ self . to_upper_camel_case ( )
3407
3501
}
3408
3502
}
3409
3503
}
0 commit comments