diff --git a/crates/bindings-csharp/BSATN.Codegen/Type.cs b/crates/bindings-csharp/BSATN.Codegen/Type.cs index ff0c2795a1..6406945837 100644 --- a/crates/bindings-csharp/BSATN.Codegen/Type.cs +++ b/crates/bindings-csharp/BSATN.Codegen/Type.cs @@ -225,10 +225,13 @@ public void Write(System.IO.BinaryWriter writer, {{ShortName}} value) { {{write}} } - public SpacetimeDB.BSATN.AlgebraicType GetAlgebraicType(SpacetimeDB.BSATN.ITypeRegistrar registrar) => + public SpacetimeDB.BSATN.AlgebraicType.Ref GetAlgebraicType(SpacetimeDB.BSATN.ITypeRegistrar registrar) => registrar.RegisterType<{{ShortName}}>(_ => new SpacetimeDB.BSATN.AlgebraicType.{{Kind}}(new SpacetimeDB.BSATN.AggregateElement[] { {{MemberDeclaration.GenerateDefs(Members)}} })); + + SpacetimeDB.BSATN.AlgebraicType SpacetimeDB.BSATN.IReadWrite<{{ShortName}}>.GetAlgebraicType(SpacetimeDB.BSATN.ITypeRegistrar registrar) => + GetAlgebraicType(registrar); } """ ); diff --git a/crates/bindings-csharp/Codegen.Tests/TestInit.cs b/crates/bindings-csharp/Codegen.Tests/TestInit.cs index 22ea757ff6..f7397cc388 100644 --- a/crates/bindings-csharp/Codegen.Tests/TestInit.cs +++ b/crates/bindings-csharp/Codegen.Tests/TestInit.cs @@ -37,5 +37,10 @@ public static void Initialize() }, ScrubberLocation.Last ); + // Auto-accept all snapshot updates when AUTO_VERIFY is set. + if (Environment.GetEnvironmentVariable("AUTO_VERIFY") == "1") + { + VerifierSettings.AutoVerify(); + } } } diff --git a/crates/bindings-csharp/Codegen.Tests/Tests.cs b/crates/bindings-csharp/Codegen.Tests/Tests.cs index 20e006bf2c..1c8548d057 100644 --- a/crates/bindings-csharp/Codegen.Tests/Tests.cs +++ b/crates/bindings-csharp/Codegen.Tests/Tests.cs @@ -97,9 +97,9 @@ static void AssertCompilationSuccessful(Compilation compilation) emitResult.Success, string.Join( "\n", - emitResult.Diagnostics.Select(diag => - CSharpDiagnosticFormatter.Instance.Format(diag) - ) + emitResult + .Diagnostics.Where(diag => diag.Severity != DiagnosticSeverity.Hidden) + .Select(diag => CSharpDiagnosticFormatter.Instance.Format(diag)) ) ); } diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/client/snapshots/Type#CustomClass.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/client/snapshots/Type#CustomClass.verified.cs index f1c7727c41..9493914333 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/client/snapshots/Type#CustomClass.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/client/snapshots/Type#CustomClass.verified.cs @@ -29,7 +29,7 @@ public void Write(System.IO.BinaryWriter writer, CustomClass value) value.WriteFields(writer); } - public SpacetimeDB.BSATN.AlgebraicType GetAlgebraicType( + public SpacetimeDB.BSATN.AlgebraicType.Ref GetAlgebraicType( SpacetimeDB.BSATN.ITypeRegistrar registrar ) => registrar.RegisterType(_ => new SpacetimeDB.BSATN.AlgebraicType.Product( @@ -39,5 +39,9 @@ SpacetimeDB.BSATN.ITypeRegistrar registrar new(nameof(StringField), StringField.GetAlgebraicType(registrar)) } )); + + SpacetimeDB.BSATN.AlgebraicType SpacetimeDB.BSATN.IReadWrite.GetAlgebraicType( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => GetAlgebraicType(registrar); } } // CustomClass diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/client/snapshots/Type#CustomStruct.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/client/snapshots/Type#CustomStruct.verified.cs index 855a5757c9..95a910c8f0 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/client/snapshots/Type#CustomStruct.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/client/snapshots/Type#CustomStruct.verified.cs @@ -29,7 +29,7 @@ public void Write(System.IO.BinaryWriter writer, CustomStruct value) value.WriteFields(writer); } - public SpacetimeDB.BSATN.AlgebraicType GetAlgebraicType( + public SpacetimeDB.BSATN.AlgebraicType.Ref GetAlgebraicType( SpacetimeDB.BSATN.ITypeRegistrar registrar ) => registrar.RegisterType(_ => new SpacetimeDB.BSATN.AlgebraicType.Product( @@ -39,5 +39,9 @@ SpacetimeDB.BSATN.ITypeRegistrar registrar new(nameof(StringField), StringField.GetAlgebraicType(registrar)) } )); + + SpacetimeDB.BSATN.AlgebraicType SpacetimeDB.BSATN.IReadWrite.GetAlgebraicType( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => GetAlgebraicType(registrar); } } // CustomStruct diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/client/snapshots/Type#CustomTaggedEnum.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/client/snapshots/Type#CustomTaggedEnum.verified.cs index 66edf6ee00..d9be5d8eb8 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/client/snapshots/Type#CustomTaggedEnum.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/client/snapshots/Type#CustomTaggedEnum.verified.cs @@ -48,7 +48,7 @@ public void Write(System.IO.BinaryWriter writer, CustomTaggedEnum value) } } - public SpacetimeDB.BSATN.AlgebraicType GetAlgebraicType( + public SpacetimeDB.BSATN.AlgebraicType.Ref GetAlgebraicType( SpacetimeDB.BSATN.ITypeRegistrar registrar ) => registrar.RegisterType(_ => new SpacetimeDB.BSATN.AlgebraicType.Sum( @@ -58,5 +58,9 @@ SpacetimeDB.BSATN.ITypeRegistrar registrar new(nameof(StringVariant), StringVariant.GetAlgebraicType(registrar)) } )); + + SpacetimeDB.BSATN.AlgebraicType SpacetimeDB.BSATN.IReadWrite.GetAlgebraicType( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => GetAlgebraicType(registrar); } } // CustomTaggedEnum diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/client/snapshots/Type#PublicTable.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/client/snapshots/Type#PublicTable.verified.cs index 212c0b2fc5..f9f0599d35 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/client/snapshots/Type#PublicTable.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/client/snapshots/Type#PublicTable.verified.cs @@ -133,7 +133,7 @@ public void Write(System.IO.BinaryWriter writer, PublicTable value) value.WriteFields(writer); } - public SpacetimeDB.BSATN.AlgebraicType GetAlgebraicType( + public SpacetimeDB.BSATN.AlgebraicType.Ref GetAlgebraicType( SpacetimeDB.BSATN.ITypeRegistrar registrar ) => registrar.RegisterType(_ => new SpacetimeDB.BSATN.AlgebraicType.Product( @@ -174,5 +174,9 @@ SpacetimeDB.BSATN.ITypeRegistrar registrar new(nameof(ComplexNestedField), ComplexNestedField.GetAlgebraicType(registrar)) } )); + + SpacetimeDB.BSATN.AlgebraicType SpacetimeDB.BSATN.IReadWrite.GetAlgebraicType( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => GetAlgebraicType(registrar); } } // PublicTable diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/Lib.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/Lib.cs index cace016747..f8857bff7c 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/server/Lib.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/Lib.cs @@ -104,7 +104,7 @@ namespace NestingNamespaces { public static partial class AndClasses { - [SpacetimeDB.Reducer("test_custom_name_and_reducer_ctx")] + [SpacetimeDB.Reducer] public static void InsertData2(ReducerContext ctx, PublicTable data) { data.Insert(); diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#FFI.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#FFI.verified.cs index 60368e8ec9..5efdd36e01 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#FFI.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#FFI.verified.cs @@ -10,9 +10,9 @@ static class ModuleRegistration { class Init : SpacetimeDB.Internal.IReducer { - public SpacetimeDB.Internal.ReducerDef MakeReducerDef( + public SpacetimeDB.Internal.RawReducerDefV9 MakeReducerDef( SpacetimeDB.BSATN.ITypeRegistrar registrar - ) => new("__init__", []); + ) => new(nameof(Init), [], SpacetimeDB.Internal.Lifecycle.Init); public void Invoke(BinaryReader reader, SpacetimeDB.ReducerContext ctx) { @@ -24,9 +24,9 @@ class InsertData : SpacetimeDB.Internal.IReducer { private static readonly PublicTable.BSATN data = new(); - public SpacetimeDB.Internal.ReducerDef MakeReducerDef( + public SpacetimeDB.Internal.RawReducerDefV9 MakeReducerDef( SpacetimeDB.BSATN.ITypeRegistrar registrar - ) => new("InsertData", [new(nameof(data), data.GetAlgebraicType(registrar))]); + ) => new(nameof(InsertData), [new(nameof(data), data.GetAlgebraicType(registrar))], null); public void Invoke(BinaryReader reader, SpacetimeDB.ReducerContext ctx) { @@ -38,13 +38,9 @@ class InsertData2 : SpacetimeDB.Internal.IReducer { private static readonly PublicTable.BSATN data = new(); - public SpacetimeDB.Internal.ReducerDef MakeReducerDef( + public SpacetimeDB.Internal.RawReducerDefV9 MakeReducerDef( SpacetimeDB.BSATN.ITypeRegistrar registrar - ) => - new( - "test_custom_name_and_reducer_ctx", - [new(nameof(data), data.GetAlgebraicType(registrar))] - ); + ) => new(nameof(InsertData2), [new(nameof(data), data.GetAlgebraicType(registrar))], null); public void Invoke(BinaryReader reader, SpacetimeDB.ReducerContext ctx) { @@ -56,9 +52,14 @@ class ScheduleImmediate : SpacetimeDB.Internal.IReducer { private static readonly PublicTable.BSATN data = new(); - public SpacetimeDB.Internal.ReducerDef MakeReducerDef( + public SpacetimeDB.Internal.RawReducerDefV9 MakeReducerDef( SpacetimeDB.BSATN.ITypeRegistrar registrar - ) => new("ScheduleImmediate", [new(nameof(data), data.GetAlgebraicType(registrar))]); + ) => + new( + nameof(ScheduleImmediate), + [new(nameof(data), data.GetAlgebraicType(registrar))], + null + ); public void Invoke(BinaryReader reader, SpacetimeDB.ReducerContext ctx) { @@ -70,9 +71,14 @@ class SendScheduledMessage : SpacetimeDB.Internal.IReducer { private static readonly Timers.SendMessageTimer.BSATN arg = new(); - public SpacetimeDB.Internal.ReducerDef MakeReducerDef( + public SpacetimeDB.Internal.RawReducerDefV9 MakeReducerDef( SpacetimeDB.BSATN.ITypeRegistrar registrar - ) => new("SendScheduledMessage", [new(nameof(arg), arg.GetAlgebraicType(registrar))]); + ) => + new( + nameof(SendScheduledMessage), + [new(nameof(arg), arg.GetAlgebraicType(registrar))], + null + ); public void Invoke(BinaryReader reader, SpacetimeDB.ReducerContext ctx) { diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#PrivateTable.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#PrivateTable.verified.cs index d3bfe38489..dc98c9b4e5 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#PrivateTable.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#PrivateTable.verified.cs @@ -18,34 +18,33 @@ public void Write(System.IO.BinaryWriter writer, PrivateTable value) value.WriteFields(writer); } - public SpacetimeDB.BSATN.AlgebraicType GetAlgebraicType( + public SpacetimeDB.BSATN.AlgebraicType.Ref GetAlgebraicType( SpacetimeDB.BSATN.ITypeRegistrar registrar ) => registrar.RegisterType(_ => new SpacetimeDB.BSATN.AlgebraicType.Product( new SpacetimeDB.BSATN.AggregateElement[] { } )); + + SpacetimeDB.BSATN.AlgebraicType SpacetimeDB.BSATN.IReadWrite.GetAlgebraicType( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => GetAlgebraicType(registrar); } void SpacetimeDB.Internal.ITable.ReadGenFields(System.IO.BinaryReader reader) { } - static SpacetimeDB.Internal.TableDesc SpacetimeDB.Internal.ITable.MakeTableDesc( + static SpacetimeDB.Internal.RawTableDefV9 SpacetimeDB.Internal.ITable.MakeTableDesc( SpacetimeDB.BSATN.ITypeRegistrar registrar ) => new( - new( - TableName: nameof(PrivateTable), - Columns: [], - Indexes: [], - Constraints: [], - Sequences: [], - // "system" | "user" - TableType: "user", - // "public" | "private" - TableAccess: "private", - Scheduled: null - ), - (uint) - ((SpacetimeDB.BSATN.AlgebraicType.Ref)new BSATN().GetAlgebraicType(registrar)).Ref_ + Name: nameof(PrivateTable), + ProductTypeRef: (uint)new BSATN().GetAlgebraicType(registrar).Ref_, + PrimaryKey: null, + Indexes: [], + Constraints: [], + Sequences: [], + Schedule: null, + TableType: SpacetimeDB.Internal.TableType.User, + TableAccess: SpacetimeDB.Internal.TableAccess.Private ); static SpacetimeDB.Internal.Filter SpacetimeDB.Internal.ITable.CreateFilter() => diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#PublicTable.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#PublicTable.verified.cs index 98cd813791..986aefb55b 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#PublicTable.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#PublicTable.verified.cs @@ -142,7 +142,7 @@ public void Write(System.IO.BinaryWriter writer, PublicTable value) value.WriteFields(writer); } - public SpacetimeDB.BSATN.AlgebraicType GetAlgebraicType( + public SpacetimeDB.BSATN.AlgebraicType.Ref GetAlgebraicType( SpacetimeDB.BSATN.ITypeRegistrar registrar ) => registrar.RegisterType(_ => new SpacetimeDB.BSATN.AlgebraicType.Product( @@ -186,6 +186,10 @@ SpacetimeDB.BSATN.ITypeRegistrar registrar new(nameof(ComplexNestedField), ComplexNestedField.GetAlgebraicType(registrar)) } )); + + SpacetimeDB.BSATN.AlgebraicType SpacetimeDB.BSATN.IReadWrite.GetAlgebraicType( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => GetAlgebraicType(registrar); } void SpacetimeDB.Internal.ITable.ReadGenFields(System.IO.BinaryReader reader) @@ -196,77 +200,22 @@ void SpacetimeDB.Internal.ITable.ReadGenFields(System.IO.BinaryRead } } - static SpacetimeDB.Internal.TableDesc SpacetimeDB.Internal.ITable.MakeTableDesc( + static SpacetimeDB.Internal.RawTableDefV9 SpacetimeDB.Internal.ITable.MakeTableDesc( SpacetimeDB.BSATN.ITypeRegistrar registrar ) => new( - new( - TableName: nameof(PublicTable), - Columns: - [ - new(nameof(Id), BSATN.Id.GetAlgebraicType(registrar)), - new(nameof(ByteField), BSATN.ByteField.GetAlgebraicType(registrar)), - new(nameof(UshortField), BSATN.UshortField.GetAlgebraicType(registrar)), - new(nameof(UintField), BSATN.UintField.GetAlgebraicType(registrar)), - new(nameof(UlongField), BSATN.UlongField.GetAlgebraicType(registrar)), - new(nameof(UInt128Field), BSATN.UInt128Field.GetAlgebraicType(registrar)), - new(nameof(U128Field), BSATN.U128Field.GetAlgebraicType(registrar)), - new(nameof(U256Field), BSATN.U256Field.GetAlgebraicType(registrar)), - new(nameof(SbyteField), BSATN.SbyteField.GetAlgebraicType(registrar)), - new(nameof(ShortField), BSATN.ShortField.GetAlgebraicType(registrar)), - new(nameof(IntField), BSATN.IntField.GetAlgebraicType(registrar)), - new(nameof(LongField), BSATN.LongField.GetAlgebraicType(registrar)), - new(nameof(Int128Field), BSATN.Int128Field.GetAlgebraicType(registrar)), - new(nameof(I128Field), BSATN.I128Field.GetAlgebraicType(registrar)), - new(nameof(I256Field), BSATN.I256Field.GetAlgebraicType(registrar)), - new(nameof(BoolField), BSATN.BoolField.GetAlgebraicType(registrar)), - new(nameof(FloatField), BSATN.FloatField.GetAlgebraicType(registrar)), - new(nameof(DoubleField), BSATN.DoubleField.GetAlgebraicType(registrar)), - new(nameof(StringField), BSATN.StringField.GetAlgebraicType(registrar)), - new(nameof(IdentityField), BSATN.IdentityField.GetAlgebraicType(registrar)), - new(nameof(AddressField), BSATN.AddressField.GetAlgebraicType(registrar)), - new( - nameof(CustomStructField), - BSATN.CustomStructField.GetAlgebraicType(registrar) - ), - new( - nameof(CustomClassField), - BSATN.CustomClassField.GetAlgebraicType(registrar) - ), - new(nameof(CustomEnumField), BSATN.CustomEnumField.GetAlgebraicType(registrar)), - new( - nameof(CustomTaggedEnumField), - BSATN.CustomTaggedEnumField.GetAlgebraicType(registrar) - ), - new(nameof(ListField), BSATN.ListField.GetAlgebraicType(registrar)), - new(nameof(DictionaryField), BSATN.DictionaryField.GetAlgebraicType(registrar)), - new( - nameof(NullableValueField), - BSATN.NullableValueField.GetAlgebraicType(registrar) - ), - new( - nameof(NullableReferenceField), - BSATN.NullableReferenceField.GetAlgebraicType(registrar) - ), - new( - nameof(ComplexNestedField), - BSATN.ComplexNestedField.GetAlgebraicType(registrar) - ) - ], - Indexes: [], - Constraints: - [ - new(nameof(PublicTable), 0, nameof(Id), SpacetimeDB.ColumnAttrs.PrimaryKeyAuto) - ], - Sequences: [], - // "system" | "user" - TableType: "user", - // "public" | "private" - TableAccess: "private", - Scheduled: null - ), - (uint) - ((SpacetimeDB.BSATN.AlgebraicType.Ref)new BSATN().GetAlgebraicType(registrar)).Ref_ + Name: nameof(PublicTable), + ProductTypeRef: (uint)new BSATN().GetAlgebraicType(registrar).Ref_, + PrimaryKey: 0, + Indexes: [], + Constraints: + [ + SpacetimeDB.Internal.ITable.MakeUniqueConstraint(0, nameof(Id)) + ], + Sequences: [SpacetimeDB.Internal.ITable.MakeSequence(0, nameof(Id))], + Schedule: null, + TableType: SpacetimeDB.Internal.TableType.User, + TableAccess: SpacetimeDB.Internal.TableAccess.Private ); static SpacetimeDB.Internal.Filter SpacetimeDB.Internal.ITable.CreateFilter() => diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#Reducers.InsertData.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#Reducers.InsertData.verified.cs index add5f82302..0b712c89b4 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#Reducers.InsertData.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#Reducers.InsertData.verified.cs @@ -9,6 +9,9 @@ public static void VolatileNonatomicScheduleImmediateInsertData(PublicTable data using var stream = new MemoryStream(); using var writer = new BinaryWriter(stream); new PublicTable.BSATN().Write(writer, data); - SpacetimeDB.Internal.IReducer.VolatileNonatomicScheduleImmediate("InsertData", stream); + SpacetimeDB.Internal.IReducer.VolatileNonatomicScheduleImmediate( + nameof(InsertData), + stream + ); } } // Reducers diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#Reducers.ScheduleImmediate.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#Reducers.ScheduleImmediate.verified.cs index 94063a3acf..0a8eab22bd 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#Reducers.ScheduleImmediate.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#Reducers.ScheduleImmediate.verified.cs @@ -10,7 +10,7 @@ public static void VolatileNonatomicScheduleImmediateScheduleImmediate(PublicTab using var writer = new BinaryWriter(stream); new PublicTable.BSATN().Write(writer, data); SpacetimeDB.Internal.IReducer.VolatileNonatomicScheduleImmediate( - "ScheduleImmediate", + nameof(ScheduleImmediate), stream ); } diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#Test.NestingNamespaces.AndClasses.InsertData2.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#Test.NestingNamespaces.AndClasses.InsertData2.verified.cs index 9d7e1ea917..876546f423 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#Test.NestingNamespaces.AndClasses.InsertData2.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#Test.NestingNamespaces.AndClasses.InsertData2.verified.cs @@ -12,7 +12,7 @@ public static void VolatileNonatomicScheduleImmediateInsertData2(PublicTable dat using var writer = new BinaryWriter(stream); new PublicTable.BSATN().Write(writer, data); SpacetimeDB.Internal.IReducer.VolatileNonatomicScheduleImmediate( - "test_custom_name_and_reducer_ctx", + nameof(InsertData2), stream ); } diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#Timers.Init.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#Timers.Init.verified.cs index 9a30e7939d..130de526f5 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#Timers.Init.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#Timers.Init.verified.cs @@ -9,6 +9,6 @@ public static void VolatileNonatomicScheduleImmediateInit() using var stream = new MemoryStream(); using var writer = new BinaryWriter(stream); - SpacetimeDB.Internal.IReducer.VolatileNonatomicScheduleImmediate("__init__", stream); + SpacetimeDB.Internal.IReducer.VolatileNonatomicScheduleImmediate(nameof(Init), stream); } } // Timers diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#Timers.SendMessageTimer.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#Timers.SendMessageTimer.verified.cs index a6ce27cbce..11449cd93e 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#Timers.SendMessageTimer.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#Timers.SendMessageTimer.verified.cs @@ -35,7 +35,7 @@ public void Write(System.IO.BinaryWriter writer, SendMessageTimer value) value.WriteFields(writer); } - public SpacetimeDB.BSATN.AlgebraicType GetAlgebraicType( + public SpacetimeDB.BSATN.AlgebraicType.Ref GetAlgebraicType( SpacetimeDB.BSATN.ITypeRegistrar registrar ) => registrar.RegisterType( @@ -48,6 +48,10 @@ SpacetimeDB.BSATN.ITypeRegistrar registrar } ) ); + + SpacetimeDB.BSATN.AlgebraicType SpacetimeDB.BSATN.IReadWrite.GetAlgebraicType( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => GetAlgebraicType(registrar); } public ulong ScheduledId; @@ -63,39 +67,33 @@ System.IO.BinaryReader reader } } - static SpacetimeDB.Internal.TableDesc SpacetimeDB.Internal.ITable.MakeTableDesc( + static SpacetimeDB.Internal.RawTableDefV9 SpacetimeDB.Internal.ITable.MakeTableDesc( SpacetimeDB.BSATN.ITypeRegistrar registrar ) => new( - new( - TableName: nameof(SendMessageTimer), - Columns: - [ - new(nameof(Text), BSATN.Text.GetAlgebraicType(registrar)), - new(nameof(ScheduledId), BSATN.ScheduledId.GetAlgebraicType(registrar)), - new(nameof(ScheduledAt), BSATN.ScheduledAt.GetAlgebraicType(registrar)) - ], - Indexes: [], - Constraints: - [ - new( - nameof(SendMessageTimer), - 1, - nameof(ScheduledId), - SpacetimeDB.ColumnAttrs.PrimaryKeyAuto - ) - ], - Sequences: [], - // "system" | "user" - TableType: "user", - // "public" | "private" - TableAccess: "private", - Scheduled: nameof(SendScheduledMessage) + Name: nameof(SendMessageTimer), + ProductTypeRef: (uint)new BSATN().GetAlgebraicType(registrar).Ref_, + PrimaryKey: 1, + Indexes: [], + Constraints: + [ + SpacetimeDB.Internal.ITable.MakeUniqueConstraint( + 1, + nameof(ScheduledId) + ) + ], + Sequences: + [ + SpacetimeDB.Internal.ITable.MakeSequence( + 1, + nameof(ScheduledId) + ) + ], + Schedule: SpacetimeDB.Internal.ITable.MakeSchedule( + nameof(SendScheduledMessage) ), - (uint) - ( - (SpacetimeDB.BSATN.AlgebraicType.Ref)new BSATN().GetAlgebraicType(registrar) - ).Ref_ + TableType: SpacetimeDB.Internal.TableType.User, + TableAccess: SpacetimeDB.Internal.TableAccess.Private ); static SpacetimeDB.Internal.Filter SpacetimeDB.Internal.ITable.CreateFilter() => diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#Timers.SendScheduledMessage.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#Timers.SendScheduledMessage.verified.cs index 0cea55149e..f627c95ea9 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#Timers.SendScheduledMessage.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#Timers.SendScheduledMessage.verified.cs @@ -12,7 +12,7 @@ Timers.SendMessageTimer arg using var writer = new BinaryWriter(stream); new Timers.SendMessageTimer.BSATN().Write(writer, arg); SpacetimeDB.Internal.IReducer.VolatileNonatomicScheduleImmediate( - "SendScheduledMessage", + nameof(SendScheduledMessage), stream ); } diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Type#CustomClass.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Type#CustomClass.verified.cs index f1c7727c41..9493914333 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Type#CustomClass.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Type#CustomClass.verified.cs @@ -29,7 +29,7 @@ public void Write(System.IO.BinaryWriter writer, CustomClass value) value.WriteFields(writer); } - public SpacetimeDB.BSATN.AlgebraicType GetAlgebraicType( + public SpacetimeDB.BSATN.AlgebraicType.Ref GetAlgebraicType( SpacetimeDB.BSATN.ITypeRegistrar registrar ) => registrar.RegisterType(_ => new SpacetimeDB.BSATN.AlgebraicType.Product( @@ -39,5 +39,9 @@ SpacetimeDB.BSATN.ITypeRegistrar registrar new(nameof(StringField), StringField.GetAlgebraicType(registrar)) } )); + + SpacetimeDB.BSATN.AlgebraicType SpacetimeDB.BSATN.IReadWrite.GetAlgebraicType( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => GetAlgebraicType(registrar); } } // CustomClass diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Type#CustomStruct.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Type#CustomStruct.verified.cs index 855a5757c9..95a910c8f0 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Type#CustomStruct.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Type#CustomStruct.verified.cs @@ -29,7 +29,7 @@ public void Write(System.IO.BinaryWriter writer, CustomStruct value) value.WriteFields(writer); } - public SpacetimeDB.BSATN.AlgebraicType GetAlgebraicType( + public SpacetimeDB.BSATN.AlgebraicType.Ref GetAlgebraicType( SpacetimeDB.BSATN.ITypeRegistrar registrar ) => registrar.RegisterType(_ => new SpacetimeDB.BSATN.AlgebraicType.Product( @@ -39,5 +39,9 @@ SpacetimeDB.BSATN.ITypeRegistrar registrar new(nameof(StringField), StringField.GetAlgebraicType(registrar)) } )); + + SpacetimeDB.BSATN.AlgebraicType SpacetimeDB.BSATN.IReadWrite.GetAlgebraicType( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => GetAlgebraicType(registrar); } } // CustomStruct diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Type#CustomTaggedEnum.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Type#CustomTaggedEnum.verified.cs index 66edf6ee00..d9be5d8eb8 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Type#CustomTaggedEnum.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Type#CustomTaggedEnum.verified.cs @@ -48,7 +48,7 @@ public void Write(System.IO.BinaryWriter writer, CustomTaggedEnum value) } } - public SpacetimeDB.BSATN.AlgebraicType GetAlgebraicType( + public SpacetimeDB.BSATN.AlgebraicType.Ref GetAlgebraicType( SpacetimeDB.BSATN.ITypeRegistrar registrar ) => registrar.RegisterType(_ => new SpacetimeDB.BSATN.AlgebraicType.Sum( @@ -58,5 +58,9 @@ SpacetimeDB.BSATN.ITypeRegistrar registrar new(nameof(StringVariant), StringVariant.GetAlgebraicType(registrar)) } )); + + SpacetimeDB.BSATN.AlgebraicType SpacetimeDB.BSATN.IReadWrite.GetAlgebraicType( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => GetAlgebraicType(registrar); } } // CustomTaggedEnum diff --git a/crates/bindings-csharp/Codegen/Module.cs b/crates/bindings-csharp/Codegen/Module.cs index efd020c185..67ac808f91 100644 --- a/crates/bindings-csharp/Codegen/Module.cs +++ b/crates/bindings-csharp/Codegen/Module.cs @@ -17,6 +17,13 @@ enum ColumnAttrs : byte PrimaryKeyAuto = PrimaryKey | AutoInc, } +enum Lifecycle +{ + Init, + OnConnect, + OnDisconnect, +} + record ColumnDeclaration : MemberDeclaration { public readonly ColumnAttrs Attrs; @@ -149,6 +156,27 @@ public TableDeclaration(GeneratorAttributeSyntaxContext context) protected override ColumnDeclaration ConvertMember(IFieldSymbol field) => new(field); + private IEnumerable<(int Pos, ColumnDeclaration Column)> GetColumnsByConstraint( + ColumnAttrs constraint + ) => + Members + .Select((Column, Pos) => (Pos, Column)) + .Where(pair => pair.Column.Attrs.HasFlag(constraint)); + + // Reimplementation of V8 -> V9 constraint conversion in Rust. + // See https://github.com/clockworklabs/SpacetimeDB/blob/13a800e9f88cbe885b98eab9e45b0fcfd3ab7014/crates/schema/src/def/validate/v8.rs#L74-L78 + // and https://github.com/clockworklabs/SpacetimeDB/blob/13a800e9f88cbe885b98eab9e45b0fcfd3ab7014/crates/lib/src/db/raw_def/v8.rs#L460-L510 + private string GenConstraintList(ColumnAttrs filterByAttr, string makeConstraintFn) => + $$""" + [ + {{string.Join( + ",\n", + GetColumnsByConstraint(filterByAttr) + .Select(pair => $"{makeConstraintFn}({pair.Pos}, nameof({pair.Column.Name}))") + )}} + ] + """; + public override Scope.Extensions ToExtensions() { var extensions = base.ToExtensions(); @@ -181,6 +209,10 @@ public override Scope.Extensions ToExtensions() extensions.BaseTypes.Clear(); extensions.BaseTypes.Add(iTable); + var primaryKey = GetColumnsByConstraint(ColumnAttrs.PrimaryKey) + .Select(pair => (int?)pair.Pos) + .SingleOrDefault(); + extensions.Contents.Append( $$""" void {{iTable}}.ReadGenFields(System.IO.BinaryReader reader) { @@ -197,40 +229,20 @@ public override Scope.Extensions ToExtensions() )}} } - static SpacetimeDB.Internal.TableDesc {{iTable}}.MakeTableDesc(SpacetimeDB.BSATN.ITypeRegistrar registrar) => new ( - new ( - TableName: nameof({{ShortName}}), - Columns: [ - {{string.Join(",\n", Members.Select(m => m.GenerateColumnDef()))}} - ], - Indexes: [], - Constraints: [ - {{string.Join( - ",\n", - Members - // Important: the position must be stored here, before filtering. - .Select((col, pos) => (col, pos)) - .Where(pair => pair.col.Attrs != ColumnAttrs.UnSet) - .Select(pair => - $$""" - new ( - nameof({{ShortName}}), - {{pair.pos}}, - nameof({{pair.col.Name}}), - SpacetimeDB.ColumnAttrs.{{pair.col.Attrs}} - ) - """ - ) - )}} - ], - Sequences: [], - // "system" | "user" - TableType: "user", - // "public" | "private" - TableAccess: "{{(IsPublic ? "public" : "private")}}", - Scheduled: {{(Scheduled is not null ? $"nameof({Scheduled})" : "null")}} - ), - (uint) ((SpacetimeDB.BSATN.AlgebraicType.Ref) new BSATN().GetAlgebraicType(registrar)).Ref_ + static SpacetimeDB.Internal.RawTableDefV9 {{iTable}}.MakeTableDesc(SpacetimeDB.BSATN.ITypeRegistrar registrar) => new ( + Name: nameof({{ShortName}}), + ProductTypeRef: (uint) new BSATN().GetAlgebraicType(registrar).Ref_, + PrimaryKey: {{primaryKey?.ToString() ?? "null"}}, + Indexes: [], + Constraints: {{GenConstraintList(ColumnAttrs.Unique, $"{iTable}.MakeUniqueConstraint")}}, + Sequences: {{GenConstraintList(ColumnAttrs.AutoInc, $"{iTable}.MakeSequence")}}, + Schedule: {{( + Scheduled is null + ? "null" + : $"{iTable}.MakeSchedule(nameof({Scheduled}))" + )}}, + TableType: SpacetimeDB.Internal.TableType.User, + TableAccess: SpacetimeDB.Internal.TableAccess.{{(IsPublic ? "Public" : "Private")}} ); static SpacetimeDB.Internal.Filter {{iTable}}.CreateFilter() => new([ @@ -295,9 +307,9 @@ public ReducerParamDeclaration(IParameterSymbol param) record ReducerDeclaration { public readonly string Name; - public readonly string ExportName; public readonly string FullName; public readonly EquatableArray Args; + public Lifecycle? Lifecycle; public readonly Scope Scope; public ReducerDeclaration(GeneratorAttributeSyntaxContext context) @@ -311,14 +323,15 @@ public ReducerDeclaration(GeneratorAttributeSyntaxContext context) throw new Exception($"Reducer {method} must return void"); } - var exportName = (string?)attr.ConstructorArguments.SingleOrDefault().Value; - Name = method.Name; - ExportName = exportName ?? Name; FullName = SymbolToName(method); Args = new( method.Parameters.Select(p => new ReducerParamDeclaration(p)).ToImmutableArray() ); + Lifecycle = attr + .ConstructorArguments.Select(a => (Lifecycle)a.Value!) + .Cast() + .SingleOrDefault(); Scope = new Scope(methodSyntax.Parent as MemberDeclarationSyntax); } @@ -330,9 +343,10 @@ public KeyValuePair GenerateClass() class {{Name}}: SpacetimeDB.Internal.IReducer { {{MemberDeclaration.GenerateBsatnFields(Accessibility.Private, NonContextArgs)}} - public SpacetimeDB.Internal.ReducerDef MakeReducerDef(SpacetimeDB.BSATN.ITypeRegistrar registrar) => new ( - "{{ExportName}}", - [{{MemberDeclaration.GenerateDefs(NonContextArgs)}}] + public SpacetimeDB.Internal.RawReducerDefV9 MakeReducerDef(SpacetimeDB.BSATN.ITypeRegistrar registrar) => new ( + nameof({{Name}}), + [{{MemberDeclaration.GenerateDefs(NonContextArgs)}}], + {{(Lifecycle is {} lifeCycle ? $"SpacetimeDB.Internal.Lifecycle.{lifeCycle}" : "null")}} ); public void Invoke(BinaryReader reader, SpacetimeDB.ReducerContext ctx) { @@ -349,7 +363,7 @@ public void Invoke(BinaryReader reader, SpacetimeDB.ReducerContext ctx) { return new(Name, class_); } - public Scope.Extensions GenerateSchedule() + public Scope.Extensions? GenerateSchedule() { var extensions = new Scope.Extensions(Scope, FullName); @@ -365,7 +379,7 @@ public Scope.Extensions GenerateSchedule() "\n", NonContextArgs.Select(a => $"new {a.TypeInfo}().Write(writer, {a.Name});") )}} - SpacetimeDB.Internal.IReducer.VolatileNonatomicScheduleImmediate("{{ExportName}}", stream); + SpacetimeDB.Internal.IReducer.VolatileNonatomicScheduleImmediate(nameof({{Name}}), stream); } """ ); @@ -404,6 +418,8 @@ public void Initialize(IncrementalGeneratorInitializationContext context) reducers .Select((r, ct) => r.GenerateSchedule()) + .Where(res => res is not null) + .Select((res, ct) => res!) .WithTrackingName("SpacetimeDB.Reducer.GenerateSchedule") .RegisterSourceOutputs(context); diff --git a/crates/bindings-csharp/Runtime/Attrs.cs b/crates/bindings-csharp/Runtime/Attrs.cs index 648c925dbc..d9c28352f3 100644 --- a/crates/bindings-csharp/Runtime/Attrs.cs +++ b/crates/bindings-csharp/Runtime/Attrs.cs @@ -1,17 +1,25 @@ namespace SpacetimeDB; -public static class ReducerKind +/// +/// This enum provides constants for special reducer kinds. +/// Do not rely on the type or values of these constants - they are only meant to be passed to the [SpacetimeDB.Reducer] attribute. +/// +public enum ReducerKind { - public const string Init = "__init__"; - public const string Update = "__update__"; - public const string Connect = "__identity_connected__"; - public const string Disconnect = "__identity_disconnected__"; + Init = Internal.Lifecycle.Init, + Connect = Internal.Lifecycle.OnConnect, + Disconnect = Internal.Lifecycle.OnDisconnect, } [AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)] -public sealed class ReducerAttribute(string? name = null) : Attribute +public sealed class ReducerAttribute : Attribute { - public string? Name => name; + public ReducerAttribute() { } + + public ReducerAttribute(ReducerKind kind) + { + _ = kind; + } } [AttributeUsage( @@ -36,7 +44,9 @@ public enum ColumnAttrs : byte PrimaryKey = Unique | 0b1000, PrimaryKeyAuto = PrimaryKey | AutoInc, - // A legacy alias, originally defined as `PrimaryKey | Identity` which is numerically same as above. + /// + /// A legacy alias, originally defined as `PrimaryKey | Identity` which is numerically same as above. + /// . PrimaryKeyIdentity = PrimaryKeyAuto, } diff --git a/crates/bindings-csharp/Runtime/Internal/IReducer.cs b/crates/bindings-csharp/Runtime/Internal/IReducer.cs index bb5c8e1fa9..bd17f5769e 100644 --- a/crates/bindings-csharp/Runtime/Internal/IReducer.cs +++ b/crates/bindings-csharp/Runtime/Internal/IReducer.cs @@ -5,7 +5,7 @@ namespace SpacetimeDB.Internal; public interface IReducer { - ReducerDef MakeReducerDef(ITypeRegistrar registrar); + RawReducerDefV9 MakeReducerDef(ITypeRegistrar registrar); // This one is not static because we need to be able to store IReducer in a list. void Invoke(BinaryReader reader, ReducerContext args); diff --git a/crates/bindings-csharp/Runtime/Internal/ITable.cs b/crates/bindings-csharp/Runtime/Internal/ITable.cs index 2233e04db8..ab29ce247f 100644 --- a/crates/bindings-csharp/Runtime/Internal/ITable.cs +++ b/crates/bindings-csharp/Runtime/Internal/ITable.cs @@ -8,7 +8,7 @@ public interface ITable : IStructuralReadWrite { // These are the methods that codegen needs to implement. void ReadGenFields(BinaryReader reader); - static abstract TableDesc MakeTableDesc(ITypeRegistrar registrar); + static abstract RawTableDefV9 MakeTableDesc(ITypeRegistrar registrar); static abstract Filter CreateFilter(); // These are static helpers that codegen can use. @@ -130,11 +130,13 @@ protected override void IterStart(out FFI.RowIter handle) => FFI._iter_by_col_eq(tableId, colId, value, (uint)value.Length, out handle); } + private static readonly string tableName = typeof(T).Name; + // Note: this must be Lazy to ensure that we don't try to get the tableId during startup, before the module is initialized. private static readonly Lazy tableId_ = new(() => { - var name_bytes = System.Text.Encoding.UTF8.GetBytes(typeof(T).Name); + var name_bytes = System.Text.Encoding.UTF8.GetBytes(tableName); FFI._table_id_from_name(name_bytes, (uint)name_bytes.Length, out var out_); return out_; }); @@ -199,4 +201,23 @@ public bool Update(T row) return true; } } + + protected static RawScheduleDefV9? MakeSchedule(string? reducerName) => + reducerName is null ? null : new(Name: $"{tableName}_schedule", ReducerName: reducerName); + + protected static RawSequenceDefV9 MakeSequence(ushort colIndex, string colName) => + new( + Name: $"seq_{tableName}_{colName}", + Column: colIndex, + Start: null, + MinValue: null, + MaxValue: null, + Increment: 1 + ); + + protected static RawConstraintDefV9 MakeUniqueConstraint(ushort colIndex, string colName) => + new( + Name: $"ct_{tableName}_{colName}_unique", + Data: new RawConstraintDataV9.Unique(new([colIndex])) + ); } diff --git a/crates/bindings-csharp/Runtime/Internal/Module.cs b/crates/bindings-csharp/Runtime/Internal/Module.cs index 2df5e436ed..848c244455 100644 --- a/crates/bindings-csharp/Runtime/Internal/Module.cs +++ b/crates/bindings-csharp/Runtime/Internal/Module.cs @@ -5,17 +5,7 @@ namespace SpacetimeDB.Internal; using SpacetimeDB; using SpacetimeDB.BSATN; -partial class RawConstraintDefV8 -{ - public RawConstraintDefV8(string tableName, ushort colIndex, string colName, ColumnAttrs attrs) - : this( - ConstraintName: $"ct_{tableName}_{colName}_{attrs}", - Constraints: (byte)attrs, - Columns: [colIndex] - ) { } -} - -partial class RawModuleDefV8 +partial class RawModuleDefV9 { // Note: this intends to generate a valid identifier, but it's not guaranteed to be unique as it's not proper mangling. // Fix it up to a different mangling scheme if it causes problems. @@ -26,9 +16,8 @@ private static string GetFriendlyName(Type type) => private void RegisterTypeName(AlgebraicType.Ref typeRef) { - MiscExports.Add( - new MiscModuleExport.TypeAlias(new(GetFriendlyName(typeof(T)), (uint)typeRef.Ref_)) - ); + var scopedName = new RawScopedTypeNameV9([], GetFriendlyName(typeof(T))); + Types.Add(new(scopedName, (uint)typeRef.Ref_, CustomOrdering: true)); } internal AlgebraicType.Ref RegisterType(Func makeType) @@ -43,14 +32,14 @@ internal AlgebraicType.Ref RegisterType(Func Reducers.Add(reducer); + internal void RegisterReducer(RawReducerDefV9 reducer) => Reducers.Add(reducer); - internal void RegisterTable(TableDesc table) => Tables.Add(table); + internal void RegisterTable(RawTableDefV9 table) => Tables.Add(table); } public static class Module { - private static readonly RawModuleDefV8 moduleDef = new(); + private static readonly RawModuleDefV9 moduleDef = new(); private static readonly List reducers = []; readonly struct TypeRegistrar() : ITypeRegistrar @@ -159,7 +148,7 @@ public static void __describe_module__(BytesSink description) try { // We need this explicit cast here to make `ToBytes` understand the types correctly. - RawModuleDef versioned = new RawModuleDef.V8BackCompat(moduleDef); + RawModuleDef versioned = new RawModuleDef.V9(moduleDef); var moduleBytes = IStructuralReadWrite.ToBytes(new RawModuleDef.BSATN(), versioned); description.Write(moduleBytes); }