Skip to content

Commit eb205ec

Browse files
SteveGibsonCLSteve
authored andcommitted
Changed C# reducer signature; Change reducer invocation method to return wether or not reducer has subscribers; Moved all ReducerEvent and ReducerArgs code into a single file (#10)
Co-authored-by: Steve <[email protected]>
1 parent d8c8a2e commit eb205ec

File tree

3 files changed

+172
-180
lines changed

3 files changed

+172
-180
lines changed

crates/cli/src/subcommands/generate/csharp.rs

Lines changed: 91 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -1149,11 +1149,21 @@ pub fn autogen_csharp_reducer(ctx: &GenCtx, reducer: &ReducerDef, namespace: &st
11491149
write!(arg_types, "{}", arg_type_str).unwrap();
11501150
}
11511151

1152+
let delegate_args = if !reducer.args.is_empty() {
1153+
format!(", {}", func_arguments.clone())
1154+
} else {
1155+
func_arguments.clone()
1156+
};
11521157
writeln!(
11531158
output,
1154-
"public static event Action<ClientApi.Event.Types.Status, Identity{arg_types}> On{func_name_pascal_case}Event;"
1159+
"public delegate void {func_name_pascal_case}Handler(ReducerEvent reducerEvent{delegate_args});"
11551160
)
1156-
.unwrap();
1161+
.unwrap();
1162+
writeln!(
1163+
output,
1164+
"public static event {func_name_pascal_case}Handler On{func_name_pascal_case}Event;"
1165+
)
1166+
.unwrap();
11571167

11581168
writeln!(output).unwrap();
11591169

@@ -1208,7 +1218,7 @@ pub fn autogen_csharp_reducer(ctx: &GenCtx, reducer: &ReducerDef, namespace: &st
12081218
writeln!(output, "[ReducerCallback(FunctionName = \"{func_name}\")]").unwrap();
12091219
writeln!(
12101220
output,
1211-
"public static void On{func_name_pascal_case}(ClientApi.Event dbEvent)"
1221+
"public static bool On{func_name_pascal_case}(ClientApi.Event dbEvent)"
12121222
)
12131223
.unwrap();
12141224
writeln!(output, "{{").unwrap();
@@ -1224,11 +1234,7 @@ pub fn autogen_csharp_reducer(ctx: &GenCtx, reducer: &ReducerDef, namespace: &st
12241234
"var args = dbEvent.FunctionCall.CallInfo.{func_name_pascal_case}Args;"
12251235
)
12261236
.unwrap();
1227-
writeln!(
1228-
output,
1229-
"On{func_name_pascal_case}Event(dbEvent.Status, Identity.From(dbEvent.CallerIdentity.ToByteArray())"
1230-
)
1231-
.unwrap();
1237+
writeln!(output, "On{func_name_pascal_case}Event(dbEvent.FunctionCall.CallInfo").unwrap();
12321238
// Write out arguments one per line
12331239
{
12341240
indent_scope!(output);
@@ -1243,13 +1249,15 @@ pub fn autogen_csharp_reducer(ctx: &GenCtx, reducer: &ReducerDef, namespace: &st
12431249
}
12441250
}
12451251
writeln!(output, ");").unwrap();
1252+
writeln!(output, "return true;").unwrap();
12461253
}
12471254
// Closing brace for if event is registered
12481255
writeln!(output, "}}").unwrap();
1256+
writeln!(output, "return false;").unwrap();
12491257
}
1250-
12511258
// Closing brace for Event parsing function
12521259
writeln!(output, "}}").unwrap();
1260+
writeln!(output).unwrap();
12531261

12541262
writeln!(output, "[DeserializeEvent(FunctionName = \"{func_name}\")]").unwrap();
12551263
writeln!(
@@ -1286,7 +1294,7 @@ pub fn autogen_csharp_reducer(ctx: &GenCtx, reducer: &ReducerDef, namespace: &st
12861294

12871295
writeln!(output, "var argsGeneric = new ReducerArgs();").unwrap();
12881296
writeln!(output, "argsGeneric.{func_name_pascal_case}Args = args;").unwrap();
1289-
writeln!(output, "dbEvent.FunctionCall.CallInfo = new ReducerEvent(ReducerType.{func_name_pascal_case}, dbEvent.Message, dbEvent.Status, argsGeneric);").unwrap();
1297+
writeln!(output, "dbEvent.FunctionCall.CallInfo = new ReducerEvent(ReducerType.{func_name_pascal_case}, \"{func_name}\", dbEvent.Timestamp, Identity.From(dbEvent.CallerIdentity.ToByteArray()), dbEvent.Message, dbEvent.Status, argsGeneric);").unwrap();
12901298
}
12911299

12921300
// Closing brace for Event parsing function
@@ -1315,51 +1323,6 @@ pub fn autogen_csharp_reducer(ctx: &GenCtx, reducer: &ReducerDef, namespace: &st
13151323
writeln!(output, "}}").unwrap();
13161324
writeln!(output).unwrap();
13171325

1318-
//ReducerArgs struct
1319-
writeln!(output, "public partial struct ReducerArgs").unwrap();
1320-
writeln!(output, "{{").unwrap();
1321-
{
1322-
indent_scope!(output);
1323-
writeln!(output, "[System.Runtime.InteropServices.FieldOffset(0)]").unwrap();
1324-
writeln!(
1325-
output,
1326-
"public {func_name_pascal_case}ArgsStruct {func_name_pascal_case}Args;"
1327-
)
1328-
.unwrap();
1329-
}
1330-
// Closing brace for struct ReducerArgs
1331-
writeln!(output, "}}").unwrap();
1332-
writeln!(output).unwrap();
1333-
1334-
//ReducerEvent
1335-
writeln!(output, "public partial class ReducerEvent").unwrap();
1336-
writeln!(output, "{{").unwrap();
1337-
{
1338-
indent_scope!(output);
1339-
writeln!(
1340-
output,
1341-
"public {func_name_pascal_case}ArgsStruct {func_name_pascal_case}Args"
1342-
)
1343-
.unwrap();
1344-
writeln!(output, "{{").unwrap();
1345-
{
1346-
indent_scope!(output);
1347-
writeln!(output, "get").unwrap();
1348-
writeln!(output, "{{").unwrap();
1349-
{
1350-
indent_scope!(output);
1351-
writeln!(output, "if (Reducer != ReducerType.{func_name_pascal_case}) throw new SpacetimeDB.ReducerMismatchException(Reducer.ToString(), \"{func_name_pascal_case}\");").unwrap();
1352-
writeln!(output, "return Args.{func_name_pascal_case}Args;").unwrap();
1353-
}
1354-
// Closing brace for struct ReducerArgs
1355-
writeln!(output, "}}").unwrap();
1356-
}
1357-
// Closing brace for struct ReducerArgs
1358-
writeln!(output, "}}").unwrap();
1359-
}
1360-
// Closing brace for struct ReducerArgs
1361-
writeln!(output, "}}").unwrap();
1362-
13631326
if use_namespace {
13641327
output.dedent(1);
13651328
writeln!(output, "}}").unwrap();
@@ -1368,23 +1331,23 @@ pub fn autogen_csharp_reducer(ctx: &GenCtx, reducer: &ReducerDef, namespace: &st
13681331
output.into_inner()
13691332
}
13701333

1371-
pub fn autogen_csharp_globals(items: &Vec<GenItem>, namespace: &str) -> Vec<(String, String)> {
1372-
let reducer_names: Vec<String> = items
1334+
pub fn autogen_csharp_globals(items: &[GenItem], namespace: &str) -> Vec<(String, String)> {
1335+
let reducers: Vec<&ReducerDef> = items
13731336
.iter()
1374-
.filter(|item| {
1375-
if let GenItem::Reducer(reducer) = item {
1376-
reducer.name != "__init__"
1337+
.map(|i| {
1338+
if let GenItem::Reducer(reducer) = i {
1339+
Some(reducer)
13771340
} else {
1378-
false
1379-
}
1380-
})
1381-
.map(|item| {
1382-
if let GenItem::Reducer(reducer) = item {
1383-
reducer.name.to_case(Case::Pascal)
1384-
} else {
1385-
unreachable!()
1341+
None
13861342
}
13871343
})
1344+
.filter(|r| r.is_some())
1345+
.flatten()
1346+
.filter(|r| r.name != "__init__")
1347+
.collect();
1348+
let reducer_names: Vec<String> = reducers
1349+
.iter()
1350+
.map(|reducer| reducer.name.to_case(Case::Pascal))
13881351
.collect();
13891352

13901353
let use_namespace = true;
@@ -1417,6 +1380,7 @@ pub fn autogen_csharp_globals(items: &Vec<GenItem>, namespace: &str) -> Vec<(Str
14171380
writeln!(output, "{{").unwrap();
14181381
{
14191382
indent_scope!(output);
1383+
writeln!(output, "None,").unwrap();
14201384
for reducer in reducer_names {
14211385
writeln!(output, "{reducer},").unwrap();
14221386
}
@@ -1430,6 +1394,9 @@ pub fn autogen_csharp_globals(items: &Vec<GenItem>, namespace: &str) -> Vec<(Str
14301394
{
14311395
indent_scope!(output);
14321396
writeln!(output, "public ReducerType Reducer {{ get; private set; }}").unwrap();
1397+
writeln!(output, "public string ReducerName {{ get; private set; }}").unwrap();
1398+
writeln!(output, "public ulong Timestamp {{ get; private set; }}").unwrap();
1399+
writeln!(output, "public SpacetimeDB.Identity Identity {{ get; private set; }}").unwrap();
14331400
writeln!(output, "public string ErrMessage {{ get; private set; }}").unwrap();
14341401
writeln!(
14351402
output,
@@ -1438,18 +1405,42 @@ pub fn autogen_csharp_globals(items: &Vec<GenItem>, namespace: &str) -> Vec<(Str
14381405
.unwrap();
14391406
writeln!(output, "private ReducerArgs Args;").unwrap();
14401407
writeln!(output).unwrap();
1441-
writeln!(output, "public ReducerEvent(ReducerType reducer, string errMessage, ClientApi.Event.Types.Status status, ReducerArgs args)").unwrap();
1408+
writeln!(output, "public ReducerEvent(ReducerType reducer, string reducerName, ulong timestamp, SpacetimeDB.Identity identity, string errMessage, ClientApi.Event.Types.Status status, ReducerArgs args)").unwrap();
14421409
writeln!(output, "{{").unwrap();
14431410
{
14441411
indent_scope!(output);
14451412
writeln!(output, "Reducer = reducer;").unwrap();
1413+
writeln!(output, "ReducerName = reducerName;").unwrap();
1414+
writeln!(output, "Timestamp = timestamp;").unwrap();
1415+
writeln!(output, "Identity = identity;").unwrap();
14461416
writeln!(output, "ErrMessage = errMessage;").unwrap();
14471417
writeln!(output, "Status = status;").unwrap();
14481418
writeln!(output, "Args = args;").unwrap();
14491419
}
14501420
// Closing brace for ctor
14511421
writeln!(output, "}}").unwrap();
14521422
writeln!(output).unwrap();
1423+
// Properties for reducer args
1424+
for reducer in &reducers {
1425+
let reducer_name = reducer.name.to_case(Case::Pascal);
1426+
writeln!(output, "public {reducer_name}ArgsStruct {reducer_name}Args").unwrap();
1427+
writeln!(output, "{{").unwrap();
1428+
{
1429+
indent_scope!(output);
1430+
writeln!(output, "get").unwrap();
1431+
writeln!(output, "{{").unwrap();
1432+
{
1433+
indent_scope!(output);
1434+
writeln!(output, "if (Reducer != ReducerType.{reducer_name}) throw new SpacetimeDB.ReducerMismatchException(Reducer.ToString(), \"{reducer_name}\");").unwrap();
1435+
writeln!(output, "return Args.{reducer_name}Args;").unwrap();
1436+
}
1437+
// Closing brace for struct ReducerArgs
1438+
writeln!(output, "}}").unwrap();
1439+
}
1440+
// Closing brace for struct ReducerArgs
1441+
writeln!(output, "}}").unwrap();
1442+
}
1443+
writeln!(output).unwrap();
14531444
writeln!(output, "public object[] GetArgsAsObjectArray()").unwrap();
14541445
writeln!(output, "{{").unwrap();
14551446
{
@@ -1458,34 +1449,29 @@ pub fn autogen_csharp_globals(items: &Vec<GenItem>, namespace: &str) -> Vec<(Str
14581449
writeln!(output, "{{").unwrap();
14591450
{
14601451
indent_scope!(output);
1461-
for item in items {
1462-
if let GenItem::Reducer(reducer) = item {
1463-
if reducer.name == "__init__" {
1464-
continue;
1465-
}
1466-
let reducer_name = reducer.name.to_case(Case::Pascal);
1467-
writeln!(output, "case ReducerType.{reducer_name}:").unwrap();
1468-
writeln!(output, "{{").unwrap();
1452+
for reducer in &reducers {
1453+
let reducer_name = reducer.name.to_case(Case::Pascal);
1454+
writeln!(output, "case ReducerType.{reducer_name}:").unwrap();
1455+
writeln!(output, "{{").unwrap();
1456+
{
1457+
indent_scope!(output);
1458+
writeln!(output, "var args = {reducer_name}Args;").unwrap();
1459+
writeln!(output, "return new object[] {{").unwrap();
14691460
{
14701461
indent_scope!(output);
1471-
writeln!(output, "var args = {reducer_name}Args;").unwrap();
1472-
writeln!(output, "return new object[] {{").unwrap();
1473-
{
1474-
indent_scope!(output);
1475-
for (i, arg) in reducer.args.iter().enumerate() {
1476-
let arg_name = arg
1477-
.name
1478-
.clone()
1479-
.unwrap_or_else(|| format!("arg_{}", i))
1480-
.to_case(Case::Pascal);
1481-
writeln!(output, "args.{arg_name},").unwrap();
1482-
}
1462+
for (i, arg) in reducer.args.iter().enumerate() {
1463+
let arg_name = arg
1464+
.name
1465+
.clone()
1466+
.unwrap_or_else(|| format!("arg_{}", i))
1467+
.to_case(Case::Pascal);
1468+
writeln!(output, "args.{arg_name},").unwrap();
14831469
}
1484-
writeln!(output, "}};").unwrap();
14851470
}
1486-
// Closing brace for switch
1487-
writeln!(output, "}}").unwrap();
1471+
writeln!(output, "}};").unwrap();
14881472
}
1473+
// Closing brace for switch
1474+
writeln!(output, "}}").unwrap();
14891475
}
14901476
writeln!(output, "default: throw new System.Exception($\"Unhandled reducer case: {{Reducer}}. Please run SpacetimeDB code generator\");").unwrap();
14911477
}
@@ -1503,7 +1489,19 @@ pub fn autogen_csharp_globals(items: &Vec<GenItem>, namespace: &str) -> Vec<(Str
15031489
"[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Explicit)]"
15041490
)
15051491
.unwrap();
1506-
writeln!(output, "public partial struct ReducerArgs {{ }}").unwrap();
1492+
writeln!(output, "public partial struct ReducerArgs").unwrap();
1493+
writeln!(output, "{{").unwrap();
1494+
{
1495+
indent_scope!(output);
1496+
for reducer in &reducers {
1497+
let reducer_name = reducer.name.to_case(Case::Pascal);
1498+
writeln!(output, "[System.Runtime.InteropServices.FieldOffset(0)]").unwrap();
1499+
writeln!(output, "public {reducer_name}ArgsStruct {reducer_name}Args;").unwrap();
1500+
}
1501+
}
1502+
// Closing brace for struct ReducerArgs
1503+
writeln!(output, "}}").unwrap();
1504+
writeln!(output).unwrap();
15071505

15081506
if use_namespace {
15091507
output.dedent(1);

crates/cli/src/subcommands/generate/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ pub fn generate<'a>(wasm_file: &'a Path, lang: Language, namespace: &'a str) ->
147147
Ok(files)
148148
}
149149

150-
fn generate_globals(ctx: &GenCtx, lang: Language, namespace: &str, items: &Vec<GenItem>) -> Vec<(String, String)> {
150+
fn generate_globals(ctx: &GenCtx, lang: Language, namespace: &str, items: &[GenItem]) -> Vec<(String, String)> {
151151
match lang {
152152
Language::Csharp => csharp::autogen_csharp_globals(items, namespace),
153153
Language::TypeScript => typescript::autogen_typescript_globals(ctx, items),

0 commit comments

Comments
 (0)