From 4324cd74366922cb2df02fffaf7bc268c7044b1f Mon Sep 17 00:00:00 2001 From: Mario Alejandro Montoya Cortes Date: Thu, 20 Nov 2025 13:05:07 -0500 Subject: [PATCH 1/3] Implement SpacetimeType for Result --- crates/bindings-csharp/BSATN.Codegen/Type.cs | 50 ++++- .../BSATN.Runtime/BSATN/AlgebraicType.cs | 4 + .../bindings-csharp/BSATN.Runtime/Builtins.cs | 74 ++++++++ crates/bindings-csharp/Codegen/Module.cs | 6 +- crates/bindings-typescript/src/index.ts | 1 + .../src/lib/algebraic_type.ts | 52 ++++++ crates/bindings-typescript/src/lib/result.ts | 36 ++++ crates/bindings-typescript/src/lib/schema.ts | 6 + .../src/lib/type_builders.ts | 114 ++++++++++++ crates/codegen/src/csharp.rs | 14 ++ crates/codegen/src/rust.rs | 7 + crates/codegen/src/typescript.rs | 14 +- crates/codegen/src/unrealcpp.rs | 26 +++ crates/lib/tests/serde.rs | 6 + .../snapshots/serde__json_mappings-2.snap | 5 +- .../tests/snapshots/serde__json_mappings.snap | 5 +- crates/pg/src/encoder.rs | 9 + crates/sats/src/algebraic_type.rs | 56 +++++- crates/sats/src/algebraic_value.rs | 39 ++++ crates/sats/src/proptest.rs | 3 +- crates/sats/src/sum_type.rs | 57 +++++- crates/sats/src/typespace.rs | 24 +++ crates/schema/src/type_for_generate.rs | 28 +++ modules/sdk-test-cs/Lib.cs | 80 ++++++++ modules/sdk-test-cs/sdk-test-cs.sln | 24 +++ modules/sdk-test-ts/src/index.ts | 35 ++++ modules/sdk-test/src/lib.rs | 10 + ...t_every_primitive_struct_string_reducer.rs | 118 ++++++++++++ .../insert_result_i_32_string_reducer.rs | 102 +++++++++++ .../insert_result_identity_string_reducer.rs | 102 +++++++++++ .../insert_result_simple_enum_i_32_reducer.rs | 104 +++++++++++ .../insert_result_string_i_32_reducer.rs | 102 +++++++++++ .../insert_result_vec_i_32_string_reducer.rs | 102 +++++++++++ .../test-client/src/module_bindings/mod.rs | 173 +++++++++++++++++- ...ult_every_primitive_struct_string_table.rs | 99 ++++++++++ ...sult_every_primitive_struct_string_type.rs | 17 ++ .../result_i_32_string_table.rs | 95 ++++++++++ .../result_i_32_string_type.rs | 15 ++ .../result_identity_string_table.rs | 95 ++++++++++ .../result_identity_string_type.rs | 15 ++ .../result_simple_enum_i_32_table.rs | 96 ++++++++++ .../result_simple_enum_i_32_type.rs | 17 ++ .../result_string_i_32_table.rs | 95 ++++++++++ .../result_string_i_32_type.rs | 15 ++ .../result_vec_i_32_string_table.rs | 95 ++++++++++ .../result_vec_i_32_string_type.rs | 15 ++ smoketests/tests/pg_wire.py | 36 +++- smoketests/tests/sql.py | 40 +++- 48 files changed, 2318 insertions(+), 15 deletions(-) create mode 100644 crates/bindings-typescript/src/lib/result.ts create mode 100644 modules/sdk-test-cs/sdk-test-cs.sln create mode 100644 sdks/rust/tests/test-client/src/module_bindings/insert_result_every_primitive_struct_string_reducer.rs create mode 100644 sdks/rust/tests/test-client/src/module_bindings/insert_result_i_32_string_reducer.rs create mode 100644 sdks/rust/tests/test-client/src/module_bindings/insert_result_identity_string_reducer.rs create mode 100644 sdks/rust/tests/test-client/src/module_bindings/insert_result_simple_enum_i_32_reducer.rs create mode 100644 sdks/rust/tests/test-client/src/module_bindings/insert_result_string_i_32_reducer.rs create mode 100644 sdks/rust/tests/test-client/src/module_bindings/insert_result_vec_i_32_string_reducer.rs create mode 100644 sdks/rust/tests/test-client/src/module_bindings/result_every_primitive_struct_string_table.rs create mode 100644 sdks/rust/tests/test-client/src/module_bindings/result_every_primitive_struct_string_type.rs create mode 100644 sdks/rust/tests/test-client/src/module_bindings/result_i_32_string_table.rs create mode 100644 sdks/rust/tests/test-client/src/module_bindings/result_i_32_string_type.rs create mode 100644 sdks/rust/tests/test-client/src/module_bindings/result_identity_string_table.rs create mode 100644 sdks/rust/tests/test-client/src/module_bindings/result_identity_string_type.rs create mode 100644 sdks/rust/tests/test-client/src/module_bindings/result_simple_enum_i_32_table.rs create mode 100644 sdks/rust/tests/test-client/src/module_bindings/result_simple_enum_i_32_type.rs create mode 100644 sdks/rust/tests/test-client/src/module_bindings/result_string_i_32_table.rs create mode 100644 sdks/rust/tests/test-client/src/module_bindings/result_string_i_32_type.rs create mode 100644 sdks/rust/tests/test-client/src/module_bindings/result_vec_i_32_string_table.rs create mode 100644 sdks/rust/tests/test-client/src/module_bindings/result_vec_i_32_string_type.rs diff --git a/crates/bindings-csharp/BSATN.Codegen/Type.cs b/crates/bindings-csharp/BSATN.Codegen/Type.cs index 4bfbf45ec7e..c2142f16535 100644 --- a/crates/bindings-csharp/BSATN.Codegen/Type.cs +++ b/crates/bindings-csharp/BSATN.Codegen/Type.cs @@ -84,6 +84,12 @@ public static TypeUse Parse(ISymbol member, ITypeSymbol typeSymbol, DiagReporter ), INamedTypeSymbol named => named.OriginalDefinition.ToString() switch { + "SpacetimeDB.Result" or "SpacetimeDB.Result" => new ResultUse( + type, + typeInfo, + Parse(member, named.TypeArguments[0], diag), + Parse(member, named.TypeArguments[1], diag) + ), "System.Collections.Generic.List" => new ListUse( type, typeInfo, @@ -101,6 +107,14 @@ public static TypeUse Parse(ISymbol member, ITypeSymbol typeSymbol, DiagReporter }; } + /// + /// Get the name of the BSATN struct for this type. + /// + public virtual string to_bsatn_string() + { + return this.BSATNName; + } + /// /// Get a statement that declares outVar and assigns (inVar1 logically-equals inVar2) to it. /// logically-equals: @@ -133,6 +147,40 @@ public abstract string EqualsStatement( public abstract string GetHashCodeStatement(string inVar, string outVar, int level = 0); } +/// +/// A use of a Result type. +/// +public sealed record ResultUse : TypeUse +{ + public TypeUse Ok { get; } + public TypeUse Err { get; } + + public string TypeName { get; } + + public ResultUse(string typeName, string typeInfo, TypeUse ok, TypeUse err) + : base(typeName, typeInfo) + { + Ok = ok; + Err = err; + TypeName = typeName; + } + + public override string to_bsatn_string() + { + return $"{TypeName}.BSATN<{Ok.BSATNName}, {Err.BSATNName}>"; + } + + public override string EqualsStatement( + string inVar1, + string inVar2, + string outVar, + int level = 0 + ) => $"var {outVar} = {inVar1} == {inVar2};"; + + public override string GetHashCodeStatement(string inVar, string outVar, int level = 0) => + $"var {outVar} = {inVar}.GetHashCode();"; +} + /// /// A use of an enum type. /// (This is a C# enum, not one of our tagged enums.) @@ -348,7 +396,7 @@ IEnumerable members return string.Join( "\n ", members.Select(m => - $"{visStr} static readonly {m.Type.BSATNName} {m.Name}{TypeUse.BsatnFieldSuffix} = new();" + $"{visStr} static readonly {m.Type.to_bsatn_string()} {m.Name}{TypeUse.BsatnFieldSuffix} = new();" ) ); } diff --git a/crates/bindings-csharp/BSATN.Runtime/BSATN/AlgebraicType.cs b/crates/bindings-csharp/BSATN.Runtime/BSATN/AlgebraicType.cs index 603feae5c78..862c40fa43a 100644 --- a/crates/bindings-csharp/BSATN.Runtime/BSATN/AlgebraicType.cs +++ b/crates/bindings-csharp/BSATN.Runtime/BSATN/AlgebraicType.cs @@ -49,4 +49,8 @@ Unit F64 // Special AlgebraicType that can be recognised by the SpacetimeDB `generate` CLI as an Option. internal static AlgebraicType MakeOption(AlgebraicType someType) => new Sum([new("some", someType), new("none", Unit)]); + + // Special AlgebraicType that can be recognised by the SpacetimeDB `generate` CLI as a Result. + internal static AlgebraicType MakeResult(AlgebraicType okType, AlgebraicType errType) => + new Sum([new("ok", okType), new("err", errType)]); } diff --git a/crates/bindings-csharp/BSATN.Runtime/Builtins.cs b/crates/bindings-csharp/BSATN.Runtime/Builtins.cs index a3478d18023..6817dc20bbd 100644 --- a/crates/bindings-csharp/BSATN.Runtime/Builtins.cs +++ b/crates/bindings-csharp/BSATN.Runtime/Builtins.cs @@ -605,3 +605,77 @@ public AlgebraicType GetAlgebraicType(ITypeRegistrar registrar) => // --- / customized --- } } + +public partial record Result : TaggedEnum<(T Ok, E Err)> +{ + public static implicit operator Result(T value) => new Ok(value); + + public static implicit operator Result(E error) => new Err(error); + + public TResult Match(Func onOk, Func onErr) => + this switch + { + Ok(var v) => onOk(v), + Err(var e) => onErr(e), + _ => throw new InvalidOperationException("Unknown Result variant."), + }; + + // ----- auto-generated ----- + + private Result() { } + + internal enum @enum : byte + { + Ok, + Err, + } + + public sealed record Ok(T Value) : Result; + + public sealed record Err(E Error) : Result; + + private enum Variant : byte + { + Ok = 0, + Err = 1, + } + + public readonly struct BSATN : IReadWrite> + where OkRW : struct, IReadWrite + where ErrRW : struct, IReadWrite + { + private static readonly SpacetimeDB.BSATN.Enum<@enum> __enumTag = new(); + private static readonly OkRW okRW = new(); + private static readonly ErrRW errRW = new(); + + public Result Read(BinaryReader reader) => + __enumTag.Read(reader) switch + { + @enum.Ok => new Ok(okRW.Read(reader)), + @enum.Err => new Err(errRW.Read(reader)), + _ => throw new InvalidOperationException(), + }; + + public void Write(BinaryWriter writer, Result value) + { + switch (value) + { + case Ok(var v): + __enumTag.Write(writer, @enum.Ok); + okRW.Write(writer, v); + break; + + case Err(var e): + __enumTag.Write(writer, @enum.Err); + errRW.Write(writer, e); + break; + } + } + + public AlgebraicType GetAlgebraicType(ITypeRegistrar registrar) => + AlgebraicType.MakeResult( + okRW.GetAlgebraicType(registrar), + errRW.GetAlgebraicType(registrar) + ); + } +} diff --git a/crates/bindings-csharp/Codegen/Module.cs b/crates/bindings-csharp/Codegen/Module.cs index 9988f7b027c..e0876c2392a 100644 --- a/crates/bindings-csharp/Codegen/Module.cs +++ b/crates/bindings-csharp/Codegen/Module.cs @@ -1168,7 +1168,7 @@ public Scope.Extensions GenerateSchedule() using var writer = new BinaryWriter(stream); {{string.Join( "\n", - Args.Select(a => $"new {a.Type.BSATNName}().Write(writer, {a.Name});") + Args.Select(a => $"new {a.Type.to_bsatn_string()}().Write(writer, {a.Name});") )}} SpacetimeDB.Internal.IReducer.VolatileNonatomicScheduleImmediate(nameof({{Name}}), stream); } @@ -1239,7 +1239,7 @@ public string GenerateClass() var result = {{FullName}}((SpacetimeDB.ProcedureContext)ctx{{invocationArgs}}); using var output = new MemoryStream(); using var writer = new BinaryWriter(output); - new {{ReturnType.BSATNName}}().Write(writer, result); + new {{ReturnType.to_bsatn_string()}}().Write(writer, result); return output.ToArray(); """; @@ -1283,7 +1283,7 @@ public Scope.Extensions GenerateSchedule() using var writer = new BinaryWriter(stream); {{string.Join( "\n", - Args.Select(a => $"new {a.Type.BSATNName}().Write(writer, {a.Name});") + Args.Select(a => $"new {a.Type.to_bsatn_string()}().Write(writer, {a.Name});") )}} SpacetimeDB.Internal.IProcedure.VolatileNonatomicScheduleImmediate(nameof({{Name}}), stream); } diff --git a/crates/bindings-typescript/src/index.ts b/crates/bindings-typescript/src/index.ts index 6e8c97d64e7..bac8310e3b0 100644 --- a/crates/bindings-typescript/src/index.ts +++ b/crates/bindings-typescript/src/index.ts @@ -9,4 +9,5 @@ export * from './lib/timestamp'; export * from './lib/util'; export * from './lib/identity'; export * from './lib/option'; +export * from './lib/result'; export * from './sdk'; diff --git a/crates/bindings-typescript/src/lib/algebraic_type.ts b/crates/bindings-typescript/src/lib/algebraic_type.ts index 82a95287eee..99a5da6623e 100644 --- a/crates/bindings-typescript/src/lib/algebraic_type.ts +++ b/crates/bindings-typescript/src/lib/algebraic_type.ts @@ -439,6 +439,36 @@ export const SumType = { } else { writer.writeByte(1); } + } else if ( + ty.variants.length == 2 && + ty.variants[0].name === 'ok' && + ty.variants[1].name === 'err' + ) { + let variantName: 'ok' | 'err'; + let innerValue: any; + let index: number; + if ('ok' in value) { + variantName = 'ok'; + innerValue = value.ok; + index = 0; + } else { + variantName = 'err'; + innerValue = value.err; + index = 1; + } + + if (index < 0) { + throw `Result serialization error: variant '${variantName}' not found in ${JSON.stringify(ty)}`; + } + + writer.writeU8(index); + + AlgebraicType.serializeValue( + writer, + ty.variants[index].algebraicType, + innerValue, + typespace + ); } else { const variant = value['tag']; const index = ty.variants.findIndex(v => v.name === variant); @@ -479,6 +509,28 @@ export const SumType = { } else { throw `Can't deserialize an option type, couldn't find ${tag} tag`; } + } else if ( + ty.variants.length == 2 && + ty.variants[0].name === 'ok' && + ty.variants[1].name === 'err' + ) { + if (tag === 0) { + const value = AlgebraicType.deserializeValue( + reader, + ty.variants[0].algebraicType, + typespace + ); + return { ok: value }; + } else if (tag === 1) { + const value = AlgebraicType.deserializeValue( + reader, + ty.variants[1].algebraicType, + typespace + ); + return { err: value }; + } else { + throw `Can't deserialize a result type, couldn't find ${tag} tag`; + } } else { const variant = ty.variants[tag]; const value = AlgebraicType.deserializeValue( diff --git a/crates/bindings-typescript/src/lib/result.ts b/crates/bindings-typescript/src/lib/result.ts new file mode 100644 index 00000000000..5ea0d682048 --- /dev/null +++ b/crates/bindings-typescript/src/lib/result.ts @@ -0,0 +1,36 @@ +import { AlgebraicType } from './algebraic_type'; + +export type ResultAlgebraicType< + T extends AlgebraicType = AlgebraicType, + E extends AlgebraicType = AlgebraicType, +> = { + tag: 'Sum'; + value: { + variants: [ + { name: 'ok'; algebraicType: T }, + { name: 'err'; algebraicType: E }, + ]; + }; +}; + +export const Result: { + getAlgebraicType< + T extends AlgebraicType = AlgebraicType, + E extends AlgebraicType = AlgebraicType, + >( + okType: T, + errType: E + ): ResultAlgebraicType; +} = { + getAlgebraicType< + T extends AlgebraicType = AlgebraicType, + E extends AlgebraicType = AlgebraicType, + >(okType: T, errType: E): ResultAlgebraicType { + return AlgebraicType.Sum({ + variants: [ + { name: 'ok', algebraicType: okType }, + { name: 'err', algebraicType: errType }, + ], + }); + }, +}; diff --git a/crates/bindings-typescript/src/lib/schema.ts b/crates/bindings-typescript/src/lib/schema.ts index 51a0edae5e7..b249ea4549a 100644 --- a/crates/bindings-typescript/src/lib/schema.ts +++ b/crates/bindings-typescript/src/lib/schema.ts @@ -16,6 +16,7 @@ import { type InferSpacetimeTypeOfTypeBuilder, type RowObj, type VariantsObj, + ResultBuilder, } from './type_builders'; import type { UntypedTableDef } from './table'; import { @@ -203,6 +204,11 @@ export function registerTypesRecursively< return new OptionBuilder( registerTypesRecursively(typeBuilder.value) ) as any; + } else if (typeBuilder instanceof ResultBuilder) { + return new ResultBuilder( + registerTypesRecursively(typeBuilder.ok), + registerTypesRecursively(typeBuilder.err) + ) as any; } else if (typeBuilder instanceof ArrayBuilder) { return new ArrayBuilder( registerTypesRecursively(typeBuilder.element) diff --git a/crates/bindings-typescript/src/lib/type_builders.ts b/crates/bindings-typescript/src/lib/type_builders.ts index 371b7ee8942..a4749fe3002 100644 --- a/crates/bindings-typescript/src/lib/type_builders.ts +++ b/crates/bindings-typescript/src/lib/type_builders.ts @@ -4,6 +4,7 @@ import type BinaryWriter from './binary_writer'; import { ConnectionId, type ConnectionIdAlgebraicType } from './connection_id'; import { Identity, type IdentityAlgebraicType } from './identity'; import { Option, type OptionAlgebraicType } from './option'; +import { Result, type ResultAlgebraicType } from './result'; import ScheduleAt, { type ScheduleAtAlgebraicType } from './schedule_at'; import type { CoerceRow } from './table'; import { TimeDuration, type TimeDurationAlgebraicType } from './time_duration'; @@ -1211,6 +1212,57 @@ export class OptionBuilder> } } +export class ResultBuilder< + Ok extends TypeBuilder, + Err extends TypeBuilder, + > + extends TypeBuilder< + InferTypeOfTypeBuilder | InferTypeOfTypeBuilder, + ResultAlgebraicType< + InferSpacetimeTypeOfTypeBuilder, + InferSpacetimeTypeOfTypeBuilder + > + > + implements + Defaultable< + InferTypeOfTypeBuilder | InferTypeOfTypeBuilder, + ResultAlgebraicType< + InferSpacetimeTypeOfTypeBuilder, + InferSpacetimeTypeOfTypeBuilder + > + > +{ + ok: Ok; + err: Err; + + constructor(ok: Ok, err: Err) { + super(Result.getAlgebraicType(ok.algebraicType, err.algebraicType)); + this.ok = ok; + this.err = err; + } + default( + value: InferTypeOfTypeBuilder | InferTypeOfTypeBuilder + ): ResultColumnBuilder< + Ok, + Err, + SetField< + DefaultMetadata, + 'defaultValue', + InferTypeOfTypeBuilder | InferTypeOfTypeBuilder + > + > { + return new ResultColumnBuilder< + Ok, + Err, + SetField< + DefaultMetadata, + 'defaultValue', + InferTypeOfTypeBuilder | InferTypeOfTypeBuilder + > + >(this, set(defaultMetadata, { defaultValue: value })); + } +} + export class ProductBuilder extends TypeBuilder< ObjectType, @@ -2653,6 +2705,54 @@ export class OptionColumnBuilder< } } +export class ResultColumnBuilder< + Ok extends TypeBuilder, + Err extends TypeBuilder, + M extends ColumnMetadata< + InferTypeOfTypeBuilder | InferTypeOfTypeBuilder + > = DefaultMetadata, + > + extends ColumnBuilder< + InferTypeOfTypeBuilder | InferTypeOfTypeBuilder, + ResultAlgebraicType< + InferSpacetimeTypeOfTypeBuilder, + InferSpacetimeTypeOfTypeBuilder + >, + M + > + implements + Defaultable< + InferTypeOfTypeBuilder | InferTypeOfTypeBuilder, + ResultAlgebraicType< + InferSpacetimeTypeOfTypeBuilder, + InferSpacetimeTypeOfTypeBuilder + > + > +{ + constructor(typeBuilder: TypeBuilder, metadata: M) { + super(typeBuilder, metadata); + } + + default( + value: InferTypeOfTypeBuilder | InferTypeOfTypeBuilder + ): ResultColumnBuilder< + Ok, + Err, + SetField< + M, + 'defaultValue', + InferTypeOfTypeBuilder | InferTypeOfTypeBuilder + > + > { + return new ResultColumnBuilder( + this.typeBuilder, + set(this.columnMetadata, { + defaultValue: value, + }) + ); + } +} + export class ProductColumnBuilder< Elements extends ElementsObj, M extends ColumnMetadata> = DefaultMetadata, @@ -3291,6 +3391,20 @@ export const t = { return new OptionBuilder(value); }, + /** + * This is a convenience method for creating a column with the {@link Result} type. + * You can create a column of the same type by constructing an enum with an `ok` and `err` variant. + * @param ok The type of the value contained in the `ok` variant of the `Result`. + * @param err The type of the value contained in the `err` variant of the `Result`. + * @returns A new {@link ResultBuilder} instance with the {@link Result} type. + */ + result, Err extends TypeBuilder>( + ok: Ok, + err: Err + ): ResultBuilder { + return new ResultBuilder(ok, err); + }, + /** * This is a convenience method for creating a column with the {@link Identity} type. * You can create a column of the same type by constructing an `object` with a single `__identity__` element. diff --git a/crates/codegen/src/csharp.rs b/crates/codegen/src/csharp.rs index c07265a6d69..d7ba9560c8c 100644 --- a/crates/codegen/src/csharp.rs +++ b/crates/codegen/src/csharp.rs @@ -1103,6 +1103,12 @@ fn ty_fmt<'a>(module: &'a ModuleDef, ty: &'a AlgebraicTypeUse) -> impl fmt::Disp AlgebraicTypeUse::TimeDuration => f.write_str("SpacetimeDB.TimeDuration"), AlgebraicTypeUse::Unit => f.write_str("SpacetimeDB.Unit"), AlgebraicTypeUse::Option(inner_ty) => write!(f, "{}?", ty_fmt(module, inner_ty)), + AlgebraicTypeUse::Result { ok_ty, err_ty } => write!( + f, + "SpacetimeDB.Result<{}, {}>", + ty_fmt(module, ok_ty), + ty_fmt(module, err_ty) + ), AlgebraicTypeUse::Array(elem_ty) => write!(f, "System.Collections.Generic.List<{}>", ty_fmt(module, elem_ty)), AlgebraicTypeUse::String => f.write_str("string"), AlgebraicTypeUse::Ref(r) => f.write_str(&type_ref_name(module, *r)), @@ -1137,6 +1143,12 @@ fn ty_fmt_with_ns<'a>(module: &'a ModuleDef, ty: &'a AlgebraicTypeUse, namespace AlgebraicTypeUse::TimeDuration => f.write_str("SpacetimeDB.TimeDuration"), AlgebraicTypeUse::Unit => f.write_str("SpacetimeDB.Unit"), AlgebraicTypeUse::Option(inner_ty) => write!(f, "{}?", ty_fmt_with_ns(module, inner_ty, namespace)), + AlgebraicTypeUse::Result { ok_ty, err_ty } => write!( + f, + "SpacetimeDB.Result<{}, {}>", + ty_fmt_with_ns(module, ok_ty, namespace), + ty_fmt_with_ns(module, err_ty, namespace) + ), AlgebraicTypeUse::Array(elem_ty) => write!( f, "System.Collections.Generic.List<{}>", @@ -1189,6 +1201,8 @@ fn default_init(ctx: &TypespaceForGenerate, ty: &AlgebraicTypeUse) -> Option<&'s | AlgebraicTypeUse::ConnectionId | AlgebraicTypeUse::Timestamp | AlgebraicTypeUse::TimeDuration => None, + // Result is a struct, initialized to the "Ok with default T" variant. + AlgebraicTypeUse::Result { .. } => None, AlgebraicTypeUse::Never => unimplemented!("never types are not yet supported in C# output"), } } diff --git a/crates/codegen/src/rust.rs b/crates/codegen/src/rust.rs index 9bcb427298c..6057a29cf28 100644 --- a/crates/codegen/src/rust.rs +++ b/crates/codegen/src/rust.rs @@ -621,6 +621,13 @@ pub fn write_type(module: &ModuleDef, out: &mut W, ty: &AlgebraicTypeU write_type(module, out, inner_ty)?; write!(out, ">")?; } + AlgebraicTypeUse::Result { ok_ty, err_ty } => { + write!(out, "Result::<")?; + write_type(module, out, ok_ty)?; + write!(out, ", ")?; + write_type(module, out, err_ty)?; + write!(out, ">")?; + } AlgebraicTypeUse::Primitive(prim) => match prim { PrimitiveType::Bool => write!(out, "bool")?, PrimitiveType::I8 => write!(out, "i8")?, diff --git a/crates/codegen/src/typescript.rs b/crates/codegen/src/typescript.rs index 254506a8f98..8f6fcdf242b 100644 --- a/crates/codegen/src/typescript.rs +++ b/crates/codegen/src/typescript.rs @@ -728,6 +728,13 @@ fn write_type_builder(module: &ModuleDef, out: &mut W, ty: &AlgebraicT write_type_builder(module, out, inner_ty)?; write!(out, ")")?; } + AlgebraicTypeUse::Result { ok_ty, err_ty } => { + write!(out, "__t.result(")?; + write_type_builder(module, out, ok_ty)?; + write!(out, ", ")?; + write_type_builder(module, out, err_ty)?; + write!(out, ")")?; + } AlgebraicTypeUse::Primitive(prim) => match prim { PrimitiveType::Bool => write!(out, "__t.bool()")?, PrimitiveType::I8 => write!(out, "__t.i8()")?, @@ -840,7 +847,7 @@ fn needs_parens_within_array(ty: &AlgebraicTypeUse) -> bool { | AlgebraicTypeUse::String => { false } - AlgebraicTypeUse::ScheduleAt | AlgebraicTypeUse::Option(_) => { + AlgebraicTypeUse::ScheduleAt | AlgebraicTypeUse::Option(_) | AlgebraicTypeUse::Result { .. } => { true } } @@ -868,6 +875,11 @@ pub fn write_type( write_type(module, out, inner_ty, ref_prefix, ref_suffix)?; write!(out, " | undefined")?; } + AlgebraicTypeUse::Result { ok_ty, err_ty } => { + write_type(module, out, ok_ty, ref_prefix, ref_suffix)?; + write!(out, " | ")?; + write_type(module, out, err_ty, ref_prefix, ref_suffix)?; + } AlgebraicTypeUse::Primitive(prim) => match prim { PrimitiveType::Bool => write!(out, "boolean")?, PrimitiveType::I8 => write!(out, "number")?, diff --git a/crates/codegen/src/unrealcpp.rs b/crates/codegen/src/unrealcpp.rs index 2fe7abd60e7..cd93321e458 100644 --- a/crates/codegen/src/unrealcpp.rs +++ b/crates/codegen/src/unrealcpp.rs @@ -4473,6 +4473,9 @@ fn should_pass_by_value_in_delegate(_module: &ModuleDef, ty: &AlgebraicTypeUse) AlgebraicTypeUse::Ref(_) => false, AlgebraicTypeUse::Array(_) => false, // Arrays use const references AlgebraicTypeUse::Option(inner) => should_pass_by_value_in_delegate(_module, inner), + AlgebraicTypeUse::Result { ok_ty, err_ty } => { + should_pass_by_value_in_delegate(_module, ok_ty) && should_pass_by_value_in_delegate(_module, err_ty) + } AlgebraicTypeUse::ScheduleAt => false, AlgebraicTypeUse::Never => false, } @@ -4520,6 +4523,9 @@ fn is_blueprintable(module: &ModuleDef, ty: &AlgebraicTypeUse) -> bool { } } AlgebraicTypeUse::Option(inner) => is_blueprintable(module, inner), + AlgebraicTypeUse::Result { ok_ty, err_ty } => { + is_blueprintable(module, ok_ty) && is_blueprintable(module, err_ty) + } AlgebraicTypeUse::Never => false, } } @@ -4553,6 +4559,9 @@ fn is_type_blueprintable_for_delegates(module: &ModuleDef, ty: &AlgebraicTypeUse } } AlgebraicTypeUse::Option(inner) => is_type_blueprintable_for_delegates(module, inner), + AlgebraicTypeUse::Result { ok_ty, err_ty } => { + is_type_blueprintable_for_delegates(module, ok_ty) && is_type_blueprintable_for_delegates(module, err_ty) + } AlgebraicTypeUse::Never => false, } } @@ -4991,6 +5000,14 @@ fn cpp_ty_fmt_impl<'a>( } } + // Result use the generated result types + AlgebraicTypeUse::Result { ok_ty, err_ty } => { + let ok_type = cpp_ty_fmt_impl(module, ok_ty, module_name).to_string(); + let err_type = cpp_ty_fmt_impl(module, err_ty, module_name).to_string(); + + write!(f, "FSpacetimeDBResult<{ok_type}, {err_type}>") + } + AlgebraicTypeUse::Never => unreachable!("never type"), }) } @@ -5028,6 +5045,8 @@ fn cpp_ty_init_fmt_impl<'a>(ty: &'a AlgebraicTypeUse) -> impl fmt::Display + 'a AlgebraicTypeUse::Ref(_r) => f.write_str(""), // Options use the generated optional types AlgebraicTypeUse::Option(_inner) => f.write_str(""), + // Result use the generated result types + AlgebraicTypeUse::Result { ok_ty: _, err_ty: _ } => f.write_str(""), AlgebraicTypeUse::Never => unreachable!("never type"), }) } @@ -5055,6 +5074,13 @@ fn collect_includes_for_type( // Also collect includes for the inner type collect_includes_for_type(module, inner, out, module_name); } + Result { ok_ty, err_ty } => { + // Add the result type header + out.insert("Types/Result.h".to_string()); + // Also collect includes for the ok and err types + collect_includes_for_type(module, ok_ty, out, module_name); + collect_includes_for_type(module, err_ty, out, module_name); + } Array(inner) => { collect_includes_for_type(module, inner, out, module_name); } diff --git a/crates/lib/tests/serde.rs b/crates/lib/tests/serde.rs index dfc6eef0957..661cc94116d 100644 --- a/crates/lib/tests/serde.rs +++ b/crates/lib/tests/serde.rs @@ -70,6 +70,10 @@ fn test_json_mappings() { enumm([("Hash", AlgebraicType::bytes()), ("Unit", AlgebraicType::unit())]).into(), ), ("and_peggy", AlgebraicType::option(AlgebraicType::F64)), + ( + "result", + AlgebraicType::result(AlgebraicType::U32, AlgebraicType::String), + ), ("identity", Identity::get_type()), ]); @@ -80,6 +84,7 @@ fn test_json_mappings() { "baz": ["heyyyyyy", "hooo"], "quux": { "Hash": "54a3e6d2b0959deaacf102292b1cbd6fcbb8cf237f73306e27ed82c3153878aa" }, "and_peggy": { "some": 3.141592653589793238426 }, + "result": { "ok": 1 }, "identity": ["0x0"] } "#; // all of those ^^^^^^ digits are from memory @@ -92,6 +97,7 @@ fn test_json_mappings() { "baz": ["it's 🥶°C"], "quux": { "Unit": [] }, "and_peggy": null, + "result": { "err": "sorry" }, "identity": ["0x0"] } "#; diff --git a/crates/lib/tests/snapshots/serde__json_mappings-2.snap b/crates/lib/tests/snapshots/serde__json_mappings-2.snap index db77cada11d..659a82a5a1b 100644 --- a/crates/lib/tests/snapshots/serde__json_mappings-2.snap +++ b/crates/lib/tests/snapshots/serde__json_mappings-2.snap @@ -1,6 +1,6 @@ --- source: crates/lib/tests/serde.rs -expression: "de_json({\n \"foo\": 5654,\n \"bar\": [1, 15, 44],\n \"baz\": [\"it's 🥶°C\"],\n \"quux\": { \"Unit\": [] },\n \"and_peggy\": null,\n \"identity\": [\"0x0\"]\n})" +expression: "de_json({\n \"foo\": 5654,\n \"bar\": [1, 15, 44],\n \"baz\": [\"it's 🥶°C\"],\n \"quux\": { \"Unit\": [] },\n \"and_peggy\": null,\n \"result\": { \"err\": \"sorry\" },\n \"identity\": [\"0x0\"]\n})" --- ( foo = 5654, @@ -14,6 +14,9 @@ expression: "de_json({\n \"foo\": 5654,\n \"bar\": [1, 15, 44],\n \"baz and_peggy = ( none = (), ), + result = ( + err = "sorry", + ), identity = ( __identity__ = 0, ), diff --git a/crates/lib/tests/snapshots/serde__json_mappings.snap b/crates/lib/tests/snapshots/serde__json_mappings.snap index 4bd8dcf4986..5f48e829bdd 100644 --- a/crates/lib/tests/snapshots/serde__json_mappings.snap +++ b/crates/lib/tests/snapshots/serde__json_mappings.snap @@ -1,6 +1,6 @@ --- source: crates/lib/tests/serde.rs -expression: "de_json({\n \"foo\": 42,\n \"bar\": \"404040FFFF0A48656C6C6F\",\n \"baz\": [\"heyyyyyy\", \"hooo\"],\n \"quux\": { \"Hash\": \"54a3e6d2b0959deaacf102292b1cbd6fcbb8cf237f73306e27ed82c3153878aa\" },\n \"and_peggy\": { \"some\": 3.141592653589793238426 },\n \"identity\": [\"0x0\"]\n})" +expression: "de_json({\n \"foo\": 42,\n \"bar\": \"404040FFFF0A48656C6C6F\",\n \"baz\": [\"heyyyyyy\", \"hooo\"],\n \"quux\": { \"Hash\": \"54a3e6d2b0959deaacf102292b1cbd6fcbb8cf237f73306e27ed82c3153878aa\" },\n \"and_peggy\": { \"some\": 3.141592653589793238426 },\n \"result\": { \"ok\": 1 },\n \"identity\": [\"0x0\"]\n})" --- ( foo = 42, @@ -15,6 +15,9 @@ expression: "de_json({\n \"foo\": 42,\n \"bar\": \"404040FFFF0A48656C6C6F\ and_peggy = ( some = 3.141592653589793, ), + result = ( + ok = 1, + ), identity = ( __identity__ = 0, ), diff --git a/crates/pg/src/encoder.rs b/crates/pg/src/encoder.rs index f5a6ed990ed..dc07f70c9e5 100644 --- a/crates/pg/src/encoder.rs +++ b/crates/pg/src/encoder.rs @@ -239,6 +239,15 @@ mod tests { let row = run(schema, value).await; assert_eq!(row, "\0\0\0\u{b}{\"some\": 1}\0\0\0\u{c}{\"none\": {}}"); + let result = AlgebraicType::result(AlgebraicType::I64, AlgebraicType::String); + let schema = ProductType::from([result.clone(), result.clone()]); + let value = product![ + AlgebraicValue::sum(0, AlgebraicValue::I64(1)), // Ok(1) + AlgebraicValue::sum(1, AlgebraicValue::String("error".into())), // Err("error") + ]; + let row = run(schema, value).await; + assert_eq!(row, "\0\0\0\t{\"ok\": 1}\0\0\0\u{10}{\"err\": \"error\"}"); + let color = AlgebraicType::Sum([SumTypeVariant::new_named(AlgebraicType::I64, "Gray")].into()); let nested = AlgebraicType::option(color.clone()); let schema = ProductType::from([color, nested]); diff --git a/crates/sats/src/algebraic_type.rs b/crates/sats/src/algebraic_type.rs index e42ba015639..8e0e1922af5 100644 --- a/crates/sats/src/algebraic_type.rs +++ b/crates/sats/src/algebraic_type.rs @@ -6,7 +6,7 @@ use crate::algebraic_value::ser::value_serialize; use crate::de::Deserialize; use crate::meta_type::MetaType; use crate::product_type::{CONNECTION_ID_TAG, IDENTITY_TAG, TIMESTAMP_TAG, TIME_DURATION_TAG}; -use crate::sum_type::{OPTION_NONE_TAG, OPTION_SOME_TAG}; +use crate::sum_type::{OPTION_NONE_TAG, OPTION_SOME_TAG, RESULT_ERR_TAG, RESULT_OK_TAG}; use crate::typespace::Typespace; use crate::{i256, u256}; use crate::{AlgebraicTypeRef, AlgebraicValue, ArrayType, ProductType, SpacetimeType, SumType, SumTypeVariant}; @@ -213,6 +213,17 @@ impl AlgebraicType { self.as_sum()?.as_option() } + /// Returns whether this type is a result type. + pub fn is_result(&self) -> bool { + matches!(self, Self::Sum(p) if p.is_result()) + } + + /// If this type is the standard result type, returns the types of the `ok` and `err` variants. + /// Otherwise, returns `None`. + pub fn as_result(&self) -> Option<(&AlgebraicType, &AlgebraicType)> { + self.as_sum()?.as_result() + } + /// Returns whether this type is scalar or a string type. pub fn is_scalar_or_string(&self) -> bool { self.is_scalar() || self.is_string() @@ -306,6 +317,12 @@ impl AlgebraicType { Self::sum([(OPTION_SOME_TAG, some_type), (OPTION_NONE_TAG, AlgebraicType::unit())]) } + /// Returns a structural result type where `ok_type` is the type for the `ok` variant + /// and `err_type` is the type for the `err` variant. + pub fn result(ok_type: Self, err_type: Self) -> Self { + Self::sum([(RESULT_OK_TAG, ok_type), (RESULT_ERR_TAG, err_type)]) + } + /// Returns an unsized array type where the element type is `ty`. pub fn array(ty: Self) -> Self { ArrayType { elem_ty: Box::new(ty) }.into() @@ -432,7 +449,7 @@ impl AlgebraicType { /// - a reference /// - a special, known type /// - a non-compound type like `U8`, `I32`, `F64`, etc. - /// - or a map, array, or option built from types that satisfy [`AlgebraicType::is_valid_for_client_type_use`] + /// - or a map, array, option, or result built from types that satisfy [`AlgebraicType::is_valid_for_client_type_use`] /// /// This method does not actually follow `Ref`s to check the types they point to, /// it only checks the structure of the type. @@ -441,6 +458,8 @@ impl AlgebraicType { AlgebraicType::Sum(sum) => { if let Some(wrapped) = sum.as_option() { wrapped.is_valid_for_client_type_use() + } else if let Some((ok_ty, err_ty)) = sum.as_result() { + ok_ty.is_valid_for_client_type_use() && err_ty.is_valid_for_client_type_use() } else { sum.is_special() || sum.is_empty() } @@ -542,6 +561,21 @@ mod tests { ); } + #[test] + fn result() { + let result = AlgebraicType::result(AlgebraicType::U8, AlgebraicType::String); + assert_eq!("(ok: U8 | err: String)", fmt_algebraic_type(&result).to_string()); + } + + #[test] + fn result_map() { + let result = AlgebraicType::result(AlgebraicType::U8, AlgebraicType::String); + assert_eq!( + "{ ty_: Sum, ok: { ty_: U8 }, err: { ty_: String } }", + fmt_map(&result).to_string() + ); + } + #[test] fn algebraic_type() { let algebraic_type = AlgebraicType::meta_type(); @@ -648,6 +682,18 @@ mod tests { ); } + #[test] + fn result_as_value() { + let result = AlgebraicType::result(AlgebraicType::U8, AlgebraicType::String); + let algebraic_type = AlgebraicType::meta_type(); + let typespace = Typespace::new(vec![algebraic_type]); + let at_ref = AlgebraicType::Ref(AlgebraicTypeRef(0)); + assert_eq!( + r#"(sum = (variants = [(name = (some = "ok"), algebraic_type = (u8 = ())), (name = (some = "err"), algebraic_type = (string = ()))]))"#, + in_space(&typespace, &at_ref, &result.as_value()).to_satn() + ); + } + #[test] fn algebraic_type_as_value() { let algebraic_type = AlgebraicType::meta_type(); @@ -718,6 +764,12 @@ mod tests { AlgebraicType::from_value(&option.as_value()).expect("No errors."); } + #[test] + fn result_from_value() { + let result = AlgebraicType::result(AlgebraicType::U8, AlgebraicType::String); + AlgebraicType::from_value(&result.as_value()).expect("No errors."); + } + #[test] fn builtin_from_value() { let u8 = AlgebraicType::U8; diff --git a/crates/sats/src/algebraic_value.rs b/crates/sats/src/algebraic_value.rs index 5b0859beeea..6fb94c1457e 100644 --- a/crates/sats/src/algebraic_value.rs +++ b/crates/sats/src/algebraic_value.rs @@ -188,6 +188,34 @@ impl AlgebraicValue { Self::sum(1, Self::unit()) } + /// Converts `self` into an `Result`, if applicable. + pub fn into_result(self) -> Result { + match self { + AlgebraicValue::Sum(sum_value) => match sum_value.tag { + 0 => Ok(*sum_value.value), + 1 => Err(*sum_value.value), + _ => Err(AlgebraicValue::Sum(sum_value)), + }, + _ => Err(self), + } + } + + /// Returns an [`AlgebraicValue`] for ` Ok: v`. + /// + /// The `Ok` variant is assigned the tag `0`. + #[inline] + pub fn ResultOk(v: Self) -> Self { + Self::sum(0, v) + } + + /// Returns an [`AlgebraicValue`] for ` Err: v`. + /// + /// The `Err` variant is assigned the tag `1`. + #[inline] + pub fn ResultErr(v: Self) -> Self { + Self::sum(1, v) + } + /// Returns an [`AlgebraicValue`] representing a sum value with `tag` and `value`. pub fn sum(tag: u8, value: Self) -> Self { Self::Sum(SumValue::new(tag, value)) @@ -343,6 +371,17 @@ mod tests { assert_eq!("(none = ())", in_space(&typespace, &option, &sum_value).to_satn(),); } + #[test] + fn result() { + let result = AlgebraicType::result(AlgebraicType::U8, AlgebraicType::String); + let ok = AlgebraicValue::ResultOk(AlgebraicValue::U8(42)); + let typespace = Typespace::new(vec![]); + assert_eq!("(ok = 42)", in_space(&typespace, &result, &ok).to_satn(),); + + let err = AlgebraicValue::ResultErr(AlgebraicValue::String("error".into())); + assert_eq!("(err = \"error\")", in_space(&typespace, &result, &err).to_satn(),); + } + #[test] fn primitive() { let u8 = AlgebraicType::U8; diff --git a/crates/sats/src/proptest.rs b/crates/sats/src/proptest.rs index f0344520714..da30690c3de 100644 --- a/crates/sats/src/proptest.rs +++ b/crates/sats/src/proptest.rs @@ -232,7 +232,7 @@ fn generate_ref(typespace_len: u32) -> BoxedStrategy { } /// Generate a type valid to be used to generate a type *use* in a client module. -/// That is, a ref, non-compound type, a special type, or an array, map, or option of the same. +/// That is, a ref, non-compound type, a special type, or an array, map, option, result of the same. fn generate_type_valid_for_client_use() -> impl Strategy { let leaf = prop_oneof![ generate_non_compound_algebraic_type(), @@ -246,6 +246,7 @@ fn generate_type_valid_for_client_use() -> impl Strategy prop_oneof![ gen_element.clone().prop_map(AlgebraicType::array), gen_element.clone().prop_map(AlgebraicType::option), + gen_element.clone().prop_map(|x| AlgebraicType::result(x.clone(), x)), ] }) } diff --git a/crates/sats/src/sum_type.rs b/crates/sats/src/sum_type.rs index 7bb26e0bb5f..4d9afca349c 100644 --- a/crates/sats/src/sum_type.rs +++ b/crates/sats/src/sum_type.rs @@ -12,6 +12,10 @@ pub const SCHEDULE_AT_TIME_TAG: &str = "Time"; pub const OPTION_SOME_TAG: &str = "some"; /// The tag used for the `none` variant of the special `option` sum type. pub const OPTION_NONE_TAG: &str = "none"; +/// The tag used for the `ok` variant of the special `result` sum type. +pub const RESULT_OK_TAG: &str = "ok"; +/// The tag used for the `err` variant of the special `result` sum type. +pub const RESULT_ERR_TAG: &str = "err"; /// A structural sum type. /// @@ -119,6 +123,55 @@ impl SumType { self.as_option().is_some() } + /// Check whether this sum type is a structural result type. + /// + /// A structural result type has `ok(T)` as its first variant and `err(E)` as its second. + /// That is, `{ ok(T), err(E) }` or `ok: T | err: E` depending on your notation. + /// Note that `ok` and `err` are lowercase, unlike Rust's `Result`. + /// Order matters, and a result type with these variants in the opposite order will not be recognized. + /// + /// If the type does look like a structural result type, returns the types `T` and `E`. + pub fn as_result(&self) -> Option<(&AlgebraicType, &AlgebraicType)> { + match &*self.variants { + [first, second] if Self::are_variants_result(first, second) => { + Some((&first.algebraic_type, &second.algebraic_type)) + } + _ => None, + } + } + + /// Check whether this sum type is a structural result type. + /// + /// A structural result type has `ok(T)` as its first variant and `err(E)` as its second. + /// That is, `{ ok(T), err(E) }` or `ok: T | err: E` depending on your notation. + /// Note that `ok` and `err` are lowercase, unlike Rust's `Result`. + /// Order matters, and a result type with these variants in the opposite order will not be recognized. + /// + /// If the type does look like a structural result type, returns the types `T` and `E`. + pub fn as_result_mut(&mut self) -> Option<(&mut AlgebraicType, &mut AlgebraicType)> { + match &mut *self.variants { + [first, second] if Self::are_variants_result(first, second) => { + Some((&mut first.algebraic_type, &mut second.algebraic_type)) + } + _ => None, + } + } + + fn are_variants_result(first: &SumTypeVariant, second: &SumTypeVariant) -> bool { + first.has_name(RESULT_OK_TAG) && second.has_name(RESULT_ERR_TAG) + } + + /// Check whether this sum type is a structural result type. + /// + /// A structural result type has `ok(T)` as its first variant and `err(E)` as its second. + /// That is, `{ ok(T), err(E) }` or `ok: T | err: E` depending on your notation. + /// Note that `ok` and `err` are lowercase, unlike Rust's `Result`. + /// + /// Order matters, and a result type with these variants in the opposite order will not be recognized. + pub fn is_result(&self) -> bool { + self.as_result().is_some() + } + /// Return whether this sum type is empty, that is, has no variants. pub fn is_empty(&self) -> bool { self.variants.is_empty() @@ -139,9 +192,9 @@ impl SumType { } } - /// Returns whether this sum type is a special known type, currently `Option` or `ScheduleAt`. + /// Returns whether this sum type is a special known type, currently `Option`, `ScheduleAt`, or `Result`. pub fn is_special(&self) -> bool { - self.is_option() || self.is_schedule_at() + self.is_option() || self.is_schedule_at() || self.is_result() } /// Returns whether this sum type is like on in C without data attached to the variants. diff --git a/crates/sats/src/typespace.rs b/crates/sats/src/typespace.rs index f7d0978d660..3f75f17c8de 100644 --- a/crates/sats/src/typespace.rs +++ b/crates/sats/src/typespace.rs @@ -290,6 +290,7 @@ pub trait GroundSpacetimeType { /// - `String` and `&str`, utf-8 string data /// - `()`, the unit type /// - `Option where T: SpacetimeType` +/// - `Result where T: SpacetimeType, E: SpacetimeType` /// - `Vec where T: SpacetimeType` /// /// (Storing collections in rows of a database table is a form of [denormalization](https://en.wikipedia.org/wiki/Denormalization).) @@ -427,6 +428,16 @@ impl_st!([] bytes::Bytes, AlgebraicType::bytes()); #[cfg(feature = "bytestring")] impl_st!([] bytestring::ByteString, AlgebraicType::String); +impl SpacetimeType for Result +where + T: SpacetimeType, + E: SpacetimeType, +{ + fn make_type(typespace: &mut S) -> AlgebraicType { + AlgebraicType::result(T::make_type(typespace), E::make_type(typespace)) + } +} + #[cfg(test)] mod tests { use crate::proptest::generate_typespace_valid_for_codegen; @@ -466,5 +477,18 @@ mod tests { assert_not_valid(AlgebraicType::option(AlgebraicType::array(AlgebraicType::option( bad_inner_1.clone(), )))); + + assert_not_valid(AlgebraicType::result(bad_inner_1.clone(), AlgebraicType::U8)); + assert_not_valid(AlgebraicType::result(AlgebraicType::U8, bad_inner_2.clone())); + + assert_not_valid(AlgebraicType::result( + AlgebraicType::array(AlgebraicType::result(bad_inner_1.clone(), AlgebraicType::U8)), + AlgebraicType::U8, + )); + + assert_not_valid(AlgebraicType::result( + AlgebraicType::U8, + AlgebraicType::array(AlgebraicType::result(AlgebraicType::U8, bad_inner_2.clone())), + )); } } diff --git a/crates/schema/src/type_for_generate.rs b/crates/schema/src/type_for_generate.rs index 6c2a259f080..a915b999b0a 100644 --- a/crates/schema/src/type_for_generate.rs +++ b/crates/schema/src/type_for_generate.rs @@ -281,6 +281,12 @@ pub enum AlgebraicTypeUse { /// A standard structural option type. Option(Arc), + /// A standard structural result type. + Result { + ok_ty: Arc, + err_ty: Arc, + }, + /// The special `ScheduleAt` type. ScheduleAt, @@ -329,6 +335,10 @@ impl AlgebraicTypeUse { AlgebraicTypeUse::Ref(ref_) => f(*ref_), AlgebraicTypeUse::Array(elem_ty) => elem_ty._for_each_ref(f), AlgebraicTypeUse::Option(elem_ty) => elem_ty._for_each_ref(f), + AlgebraicTypeUse::Result { ok_ty, err_ty } => { + ok_ty._for_each_ref(f); + err_ty._for_each_ref(f); + } _ => {} } } @@ -398,6 +408,12 @@ impl TypespaceForGenerateBuilder<'_> { let elem_ty = self.parse_use(elem_ty)?; let interned = self.intern_use(elem_ty); Ok(AlgebraicTypeUse::Option(interned)) + } else if let Some((ok_ty, err_ty)) = ty.as_result() { + let ok = self.parse_use(ok_ty)?; + let err = self.parse_use(err_ty)?; + let ok_ty = self.intern_use(ok); + let err_ty = self.intern_use(err); + Ok(AlgebraicTypeUse::Result { ok_ty, err_ty }) } else if ty.is_schedule_at() { Ok(AlgebraicTypeUse::ScheduleAt) } else { @@ -708,11 +724,19 @@ mod tests { let ref1 = t.add(AlgebraicType::array(AlgebraicType::Ref(def))); let ref2 = t.add(AlgebraicType::option(AlgebraicType::Ref(ref1))); let ref3 = t.add(AlgebraicType::Ref(ref2)); + let ref4 = t.add(AlgebraicType::result( + AlgebraicType::Ref(ref3), + AlgebraicType::Ref(ref2), + )); let expected_0 = AlgebraicTypeUse::Ref(def); let expected_1 = AlgebraicTypeUse::Array(Arc::new(expected_0.clone())); let expected_2 = AlgebraicTypeUse::Option(Arc::new(expected_1.clone())); let expected_3 = expected_2.clone(); + let expected_4 = AlgebraicTypeUse::Result { + ok_ty: Arc::new(expected_3.clone()), + err_ty: Arc::new(expected_2.clone()), + }; let mut for_generate_forward = TypespaceForGenerate::builder(&t, [def]); for_generate_forward.add_definition(def).unwrap(); @@ -720,13 +744,16 @@ mod tests { let use1 = for_generate_forward.parse_use(&ref1.into()).unwrap(); let use2 = for_generate_forward.parse_use(&ref2.into()).unwrap(); let use3 = for_generate_forward.parse_use(&ref3.into()).unwrap(); + let use4 = for_generate_forward.parse_use(&ref4.into()).unwrap(); assert_eq!(use0, expected_0); assert_eq!(use1, expected_1); assert_eq!(use2, expected_2); assert_eq!(use3, expected_3); + assert_eq!(use4, expected_4); let mut for_generate_backward = TypespaceForGenerate::builder(&t, [def]); + let use4 = for_generate_backward.parse_use(&ref4.into()).unwrap(); let use3 = for_generate_forward.parse_use(&ref3.into()).unwrap(); let use2 = for_generate_forward.parse_use(&ref2.into()).unwrap(); let use1 = for_generate_forward.parse_use(&ref1.into()).unwrap(); @@ -737,6 +764,7 @@ mod tests { assert_eq!(use1, expected_1); assert_eq!(use2, expected_2); assert_eq!(use3, expected_3); + assert_eq!(use4, expected_4); } #[test] diff --git a/modules/sdk-test-cs/Lib.cs b/modules/sdk-test-cs/Lib.cs index b17daa81ad4..f1e6b78c02f 100644 --- a/modules/sdk-test-cs/Lib.cs +++ b/modules/sdk-test-cs/Lib.cs @@ -767,6 +767,86 @@ public static void insert_option_every_primitive_struct( ctx.Db.option_every_primitive_struct.Insert(new OptionEveryPrimitiveStruct { s = s }); } + [Table(Name = "result_i32_string", Public = true)] + public partial struct ResultI32String + { + public Result r; + } + + [Reducer] + public static void insert_result_i32_string(ReducerContext ctx, Result r) + { + ctx.Db.result_i32_string.Insert(new ResultI32String { r = r }); + } + + [Table(Name = "result_string_i32", Public = true)] + public partial struct ResultStringI32 + { + public Result r; + } + + [Reducer] + public static void insert_result_string_i32(ReducerContext ctx, Result r) + { + ctx.Db.result_string_i32.Insert(new ResultStringI32 { r = r }); + } + + [Table(Name = "result_identity_string", Public = true)] + public partial struct ResultIdentityString + { + public Result r; + } + + [Reducer] + public static void insert_result_identity_string(ReducerContext ctx, Result r) + { + ctx.Db.result_identity_string.Insert(new ResultIdentityString { r = r }); + } + + [Table(Name = "result_simple_enum_i32", Public = true)] + public partial struct ResultSimpleEnumI32 + { + public Result r; + } + + [Reducer] + public static void insert_result_simple_enum_i32(ReducerContext ctx, Result r) + { + ctx.Db.result_simple_enum_i32.Insert(new ResultSimpleEnumI32 { r = r }); + } + + [Table(Name = "result_every_primitive_struct_string", Public = true)] + public partial struct ResultEveryPrimitiveStructString + { + public Result r; + } + + [Reducer] + public static void insert_result_every_primitive_struct_string( + ReducerContext ctx, + Result r + ) + { + ctx.Db.result_every_primitive_struct_string.Insert( + new ResultEveryPrimitiveStructString { r = r } + ); + } + + [Table(Name = "result_vec_i32_string", Public = true)] + public partial struct ResultVecI32String + { + public Result, string> r; + } + + [Reducer] + public static void insert_result_vec_i32_string( + ReducerContext ctx, + Result, string> r + ) + { + ctx.Db.result_vec_i32_string.Insert(new ResultVecI32String { r = r }); + } + [SpacetimeDB.Table(Name = "option_vec_option_i32", Public = true)] public partial struct OptionVecOptionI32 { diff --git a/modules/sdk-test-cs/sdk-test-cs.sln b/modules/sdk-test-cs/sdk-test-cs.sln new file mode 100644 index 00000000000..651c824c299 --- /dev/null +++ b/modules/sdk-test-cs/sdk-test-cs.sln @@ -0,0 +1,24 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.5.2.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "sdk-test-cs", "sdk-test-cs.csproj", "{A8BDE7A4-453D-5B7A-BB1B-A86E6E17160F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {A8BDE7A4-453D-5B7A-BB1B-A86E6E17160F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A8BDE7A4-453D-5B7A-BB1B-A86E6E17160F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A8BDE7A4-453D-5B7A-BB1B-A86E6E17160F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A8BDE7A4-453D-5B7A-BB1B-A86E6E17160F}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {34AFEE93-AA55-4929-BAB6-14A94C3A0DD4} + EndGlobalSection +EndGlobal diff --git a/modules/sdk-test-ts/src/index.ts b/modules/sdk-test-ts/src/index.ts index 76bc93e1748..fd521ef5135 100644 --- a/modules/sdk-test-ts/src/index.ts +++ b/modules/sdk-test-ts/src/index.ts @@ -316,6 +316,40 @@ const optionTables = [ ), ] as const; +// Tables for Result values. +const resultTables = [ + tbl( + 'result_i32_string', + { insert: 'insert_result_i32_string' }, + { r: t.result(t.i32(), t.string()) } + ), + tbl( + 'result_string_i32', + { insert: 'insert_result_string_i32' }, + { r: t.result(t.string(), t.i32()) } + ), + tbl( + 'result_identity_string', + { insert: 'insert_result_identity_string' }, + { r: t.result(t.identity(), t.string()) } + ), + tbl( + 'result_simple_enum_i32', + { insert: 'insert_result_simple_enum_i32' }, + { r: t.result(SimpleEnum, t.i32()) } + ), + tbl( + 'result_every_primitive_struct_string', + { insert: 'insert_result_every_primitive_struct_string' }, + { r: t.result(EveryPrimitiveStruct, t.string()) } + ), + tbl( + 'result_vec_i32_string', + { insert: 'insert_result_vec_i32_string' }, + { r: t.result(t.array(t.i32()), t.string()) } + ), +] as const; + // Tables mapping a unique, but non-pk, key to a boring i32 payload. // This allows us to test delete events, and the semantically correct absence of update events. const uniqueTables = [ @@ -717,6 +751,7 @@ const allTables = [ ...singleValTables, ...vecTables, ...optionTables, + ...resultTables, ...uniqueTables, ...pkTables, ...weirdTables, diff --git a/modules/sdk-test/src/lib.rs b/modules/sdk-test/src/lib.rs index c4dda5aeae3..81a62e324af 100644 --- a/modules/sdk-test/src/lib.rs +++ b/modules/sdk-test/src/lib.rs @@ -335,6 +335,16 @@ define_tables! { OptionVecOptionI32 { insert insert_option_vec_option_i32 } v Option>>; } +// Tables holding a Result of various types. +define_tables! { + ResultI32String { insert insert_result_i32_string } r Result; + ResultStringI32 { insert insert_result_string_i32 } r Result; + ResultIdentityString { insert insert_result_identity_string } r Result; + ResultSimpleEnumI32 { insert insert_result_simple_enum_i32 } r Result; + ResultEveryPrimitiveStructString { insert insert_result_every_primitive_struct_string } r Result; + ResultVecI32String { insert insert_result_vec_i32_string } r Result, String>; +} + // Tables mapping a unique, but non-pk, key to a boring i32 payload. // This allows us to test delete events, and the semantically correct absence of update events. define_tables! { diff --git a/sdks/rust/tests/test-client/src/module_bindings/insert_result_every_primitive_struct_string_reducer.rs b/sdks/rust/tests/test-client/src/module_bindings/insert_result_every_primitive_struct_string_reducer.rs new file mode 100644 index 00000000000..cc02e7ac327 --- /dev/null +++ b/sdks/rust/tests/test-client/src/module_bindings/insert_result_every_primitive_struct_string_reducer.rs @@ -0,0 +1,118 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#![allow(unused, clippy::all)] +use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; + +use super::every_primitive_struct_type::EveryPrimitiveStruct; + +#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)] +#[sats(crate = __lib)] +pub(super) struct InsertResultEveryPrimitiveStructStringArgs { + pub r: Result, +} + +impl From for super::Reducer { + fn from(args: InsertResultEveryPrimitiveStructStringArgs) -> Self { + Self::InsertResultEveryPrimitiveStructString { r: args.r } + } +} + +impl __sdk::InModule for InsertResultEveryPrimitiveStructStringArgs { + type Module = super::RemoteModule; +} + +pub struct InsertResultEveryPrimitiveStructStringCallbackId(__sdk::CallbackId); + +#[allow(non_camel_case_types)] +/// Extension trait for access to the reducer `insert_result_every_primitive_struct_string`. +/// +/// Implemented for [`super::RemoteReducers`]. +pub trait insert_result_every_primitive_struct_string { + /// Request that the remote module invoke the reducer `insert_result_every_primitive_struct_string` to run as soon as possible. + /// + /// This method returns immediately, and errors only if we are unable to send the request. + /// The reducer will run asynchronously in the future, + /// and its status can be observed by listening for [`Self::on_insert_result_every_primitive_struct_string`] callbacks. + fn insert_result_every_primitive_struct_string(&self, r: Result) + -> __sdk::Result<()>; + /// Register a callback to run whenever we are notified of an invocation of the reducer `insert_result_every_primitive_struct_string`. + /// + /// Callbacks should inspect the [`__sdk::ReducerEvent`] contained in the [`super::ReducerEventContext`] + /// to determine the reducer's status. + /// + /// The returned [`InsertResultEveryPrimitiveStructStringCallbackId`] can be passed to [`Self::remove_on_insert_result_every_primitive_struct_string`] + /// to cancel the callback. + fn on_insert_result_every_primitive_struct_string( + &self, + callback: impl FnMut(&super::ReducerEventContext, &Result) + Send + 'static, + ) -> InsertResultEveryPrimitiveStructStringCallbackId; + /// Cancel a callback previously registered by [`Self::on_insert_result_every_primitive_struct_string`], + /// causing it not to run in the future. + fn remove_on_insert_result_every_primitive_struct_string( + &self, + callback: InsertResultEveryPrimitiveStructStringCallbackId, + ); +} + +impl insert_result_every_primitive_struct_string for super::RemoteReducers { + fn insert_result_every_primitive_struct_string( + &self, + r: Result, + ) -> __sdk::Result<()> { + self.imp.call_reducer( + "insert_result_every_primitive_struct_string", + InsertResultEveryPrimitiveStructStringArgs { r }, + ) + } + fn on_insert_result_every_primitive_struct_string( + &self, + mut callback: impl FnMut(&super::ReducerEventContext, &Result) + Send + 'static, + ) -> InsertResultEveryPrimitiveStructStringCallbackId { + InsertResultEveryPrimitiveStructStringCallbackId(self.imp.on_reducer( + "insert_result_every_primitive_struct_string", + Box::new(move |ctx: &super::ReducerEventContext| { + let super::ReducerEventContext { + event: + __sdk::ReducerEvent { + reducer: super::Reducer::InsertResultEveryPrimitiveStructString { r }, + .. + }, + .. + } = ctx + else { + unreachable!() + }; + callback(ctx, r) + }), + )) + } + fn remove_on_insert_result_every_primitive_struct_string( + &self, + callback: InsertResultEveryPrimitiveStructStringCallbackId, + ) { + self.imp + .remove_on_reducer("insert_result_every_primitive_struct_string", callback.0) + } +} + +#[allow(non_camel_case_types)] +#[doc(hidden)] +/// Extension trait for setting the call-flags for the reducer `insert_result_every_primitive_struct_string`. +/// +/// Implemented for [`super::SetReducerFlags`]. +/// +/// This type is currently unstable and may be removed without a major version bump. +pub trait set_flags_for_insert_result_every_primitive_struct_string { + /// Set the call-reducer flags for the reducer `insert_result_every_primitive_struct_string` to `flags`. + /// + /// This type is currently unstable and may be removed without a major version bump. + fn insert_result_every_primitive_struct_string(&self, flags: __ws::CallReducerFlags); +} + +impl set_flags_for_insert_result_every_primitive_struct_string for super::SetReducerFlags { + fn insert_result_every_primitive_struct_string(&self, flags: __ws::CallReducerFlags) { + self.imp + .set_call_reducer_flags("insert_result_every_primitive_struct_string", flags); + } +} diff --git a/sdks/rust/tests/test-client/src/module_bindings/insert_result_i_32_string_reducer.rs b/sdks/rust/tests/test-client/src/module_bindings/insert_result_i_32_string_reducer.rs new file mode 100644 index 00000000000..0ebbc51d558 --- /dev/null +++ b/sdks/rust/tests/test-client/src/module_bindings/insert_result_i_32_string_reducer.rs @@ -0,0 +1,102 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#![allow(unused, clippy::all)] +use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; + +#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)] +#[sats(crate = __lib)] +pub(super) struct InsertResultI32StringArgs { + pub r: Result, +} + +impl From for super::Reducer { + fn from(args: InsertResultI32StringArgs) -> Self { + Self::InsertResultI32String { r: args.r } + } +} + +impl __sdk::InModule for InsertResultI32StringArgs { + type Module = super::RemoteModule; +} + +pub struct InsertResultI32StringCallbackId(__sdk::CallbackId); + +#[allow(non_camel_case_types)] +/// Extension trait for access to the reducer `insert_result_i32_string`. +/// +/// Implemented for [`super::RemoteReducers`]. +pub trait insert_result_i_32_string { + /// Request that the remote module invoke the reducer `insert_result_i32_string` to run as soon as possible. + /// + /// This method returns immediately, and errors only if we are unable to send the request. + /// The reducer will run asynchronously in the future, + /// and its status can be observed by listening for [`Self::on_insert_result_i_32_string`] callbacks. + fn insert_result_i_32_string(&self, r: Result) -> __sdk::Result<()>; + /// Register a callback to run whenever we are notified of an invocation of the reducer `insert_result_i32_string`. + /// + /// Callbacks should inspect the [`__sdk::ReducerEvent`] contained in the [`super::ReducerEventContext`] + /// to determine the reducer's status. + /// + /// The returned [`InsertResultI32StringCallbackId`] can be passed to [`Self::remove_on_insert_result_i_32_string`] + /// to cancel the callback. + fn on_insert_result_i_32_string( + &self, + callback: impl FnMut(&super::ReducerEventContext, &Result) + Send + 'static, + ) -> InsertResultI32StringCallbackId; + /// Cancel a callback previously registered by [`Self::on_insert_result_i_32_string`], + /// causing it not to run in the future. + fn remove_on_insert_result_i_32_string(&self, callback: InsertResultI32StringCallbackId); +} + +impl insert_result_i_32_string for super::RemoteReducers { + fn insert_result_i_32_string(&self, r: Result) -> __sdk::Result<()> { + self.imp + .call_reducer("insert_result_i32_string", InsertResultI32StringArgs { r }) + } + fn on_insert_result_i_32_string( + &self, + mut callback: impl FnMut(&super::ReducerEventContext, &Result) + Send + 'static, + ) -> InsertResultI32StringCallbackId { + InsertResultI32StringCallbackId(self.imp.on_reducer( + "insert_result_i32_string", + Box::new(move |ctx: &super::ReducerEventContext| { + let super::ReducerEventContext { + event: + __sdk::ReducerEvent { + reducer: super::Reducer::InsertResultI32String { r }, + .. + }, + .. + } = ctx + else { + unreachable!() + }; + callback(ctx, r) + }), + )) + } + fn remove_on_insert_result_i_32_string(&self, callback: InsertResultI32StringCallbackId) { + self.imp.remove_on_reducer("insert_result_i32_string", callback.0) + } +} + +#[allow(non_camel_case_types)] +#[doc(hidden)] +/// Extension trait for setting the call-flags for the reducer `insert_result_i32_string`. +/// +/// Implemented for [`super::SetReducerFlags`]. +/// +/// This type is currently unstable and may be removed without a major version bump. +pub trait set_flags_for_insert_result_i_32_string { + /// Set the call-reducer flags for the reducer `insert_result_i32_string` to `flags`. + /// + /// This type is currently unstable and may be removed without a major version bump. + fn insert_result_i_32_string(&self, flags: __ws::CallReducerFlags); +} + +impl set_flags_for_insert_result_i_32_string for super::SetReducerFlags { + fn insert_result_i_32_string(&self, flags: __ws::CallReducerFlags) { + self.imp.set_call_reducer_flags("insert_result_i32_string", flags); + } +} diff --git a/sdks/rust/tests/test-client/src/module_bindings/insert_result_identity_string_reducer.rs b/sdks/rust/tests/test-client/src/module_bindings/insert_result_identity_string_reducer.rs new file mode 100644 index 00000000000..8de7d62c464 --- /dev/null +++ b/sdks/rust/tests/test-client/src/module_bindings/insert_result_identity_string_reducer.rs @@ -0,0 +1,102 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#![allow(unused, clippy::all)] +use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; + +#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)] +#[sats(crate = __lib)] +pub(super) struct InsertResultIdentityStringArgs { + pub r: Result<__sdk::Identity, String>, +} + +impl From for super::Reducer { + fn from(args: InsertResultIdentityStringArgs) -> Self { + Self::InsertResultIdentityString { r: args.r } + } +} + +impl __sdk::InModule for InsertResultIdentityStringArgs { + type Module = super::RemoteModule; +} + +pub struct InsertResultIdentityStringCallbackId(__sdk::CallbackId); + +#[allow(non_camel_case_types)] +/// Extension trait for access to the reducer `insert_result_identity_string`. +/// +/// Implemented for [`super::RemoteReducers`]. +pub trait insert_result_identity_string { + /// Request that the remote module invoke the reducer `insert_result_identity_string` to run as soon as possible. + /// + /// This method returns immediately, and errors only if we are unable to send the request. + /// The reducer will run asynchronously in the future, + /// and its status can be observed by listening for [`Self::on_insert_result_identity_string`] callbacks. + fn insert_result_identity_string(&self, r: Result<__sdk::Identity, String>) -> __sdk::Result<()>; + /// Register a callback to run whenever we are notified of an invocation of the reducer `insert_result_identity_string`. + /// + /// Callbacks should inspect the [`__sdk::ReducerEvent`] contained in the [`super::ReducerEventContext`] + /// to determine the reducer's status. + /// + /// The returned [`InsertResultIdentityStringCallbackId`] can be passed to [`Self::remove_on_insert_result_identity_string`] + /// to cancel the callback. + fn on_insert_result_identity_string( + &self, + callback: impl FnMut(&super::ReducerEventContext, &Result<__sdk::Identity, String>) + Send + 'static, + ) -> InsertResultIdentityStringCallbackId; + /// Cancel a callback previously registered by [`Self::on_insert_result_identity_string`], + /// causing it not to run in the future. + fn remove_on_insert_result_identity_string(&self, callback: InsertResultIdentityStringCallbackId); +} + +impl insert_result_identity_string for super::RemoteReducers { + fn insert_result_identity_string(&self, r: Result<__sdk::Identity, String>) -> __sdk::Result<()> { + self.imp + .call_reducer("insert_result_identity_string", InsertResultIdentityStringArgs { r }) + } + fn on_insert_result_identity_string( + &self, + mut callback: impl FnMut(&super::ReducerEventContext, &Result<__sdk::Identity, String>) + Send + 'static, + ) -> InsertResultIdentityStringCallbackId { + InsertResultIdentityStringCallbackId(self.imp.on_reducer( + "insert_result_identity_string", + Box::new(move |ctx: &super::ReducerEventContext| { + let super::ReducerEventContext { + event: + __sdk::ReducerEvent { + reducer: super::Reducer::InsertResultIdentityString { r }, + .. + }, + .. + } = ctx + else { + unreachable!() + }; + callback(ctx, r) + }), + )) + } + fn remove_on_insert_result_identity_string(&self, callback: InsertResultIdentityStringCallbackId) { + self.imp.remove_on_reducer("insert_result_identity_string", callback.0) + } +} + +#[allow(non_camel_case_types)] +#[doc(hidden)] +/// Extension trait for setting the call-flags for the reducer `insert_result_identity_string`. +/// +/// Implemented for [`super::SetReducerFlags`]. +/// +/// This type is currently unstable and may be removed without a major version bump. +pub trait set_flags_for_insert_result_identity_string { + /// Set the call-reducer flags for the reducer `insert_result_identity_string` to `flags`. + /// + /// This type is currently unstable and may be removed without a major version bump. + fn insert_result_identity_string(&self, flags: __ws::CallReducerFlags); +} + +impl set_flags_for_insert_result_identity_string for super::SetReducerFlags { + fn insert_result_identity_string(&self, flags: __ws::CallReducerFlags) { + self.imp.set_call_reducer_flags("insert_result_identity_string", flags); + } +} diff --git a/sdks/rust/tests/test-client/src/module_bindings/insert_result_simple_enum_i_32_reducer.rs b/sdks/rust/tests/test-client/src/module_bindings/insert_result_simple_enum_i_32_reducer.rs new file mode 100644 index 00000000000..908f257c1df --- /dev/null +++ b/sdks/rust/tests/test-client/src/module_bindings/insert_result_simple_enum_i_32_reducer.rs @@ -0,0 +1,104 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#![allow(unused, clippy::all)] +use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; + +use super::simple_enum_type::SimpleEnum; + +#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)] +#[sats(crate = __lib)] +pub(super) struct InsertResultSimpleEnumI32Args { + pub r: Result, +} + +impl From for super::Reducer { + fn from(args: InsertResultSimpleEnumI32Args) -> Self { + Self::InsertResultSimpleEnumI32 { r: args.r } + } +} + +impl __sdk::InModule for InsertResultSimpleEnumI32Args { + type Module = super::RemoteModule; +} + +pub struct InsertResultSimpleEnumI32CallbackId(__sdk::CallbackId); + +#[allow(non_camel_case_types)] +/// Extension trait for access to the reducer `insert_result_simple_enum_i32`. +/// +/// Implemented for [`super::RemoteReducers`]. +pub trait insert_result_simple_enum_i_32 { + /// Request that the remote module invoke the reducer `insert_result_simple_enum_i32` to run as soon as possible. + /// + /// This method returns immediately, and errors only if we are unable to send the request. + /// The reducer will run asynchronously in the future, + /// and its status can be observed by listening for [`Self::on_insert_result_simple_enum_i_32`] callbacks. + fn insert_result_simple_enum_i_32(&self, r: Result) -> __sdk::Result<()>; + /// Register a callback to run whenever we are notified of an invocation of the reducer `insert_result_simple_enum_i32`. + /// + /// Callbacks should inspect the [`__sdk::ReducerEvent`] contained in the [`super::ReducerEventContext`] + /// to determine the reducer's status. + /// + /// The returned [`InsertResultSimpleEnumI32CallbackId`] can be passed to [`Self::remove_on_insert_result_simple_enum_i_32`] + /// to cancel the callback. + fn on_insert_result_simple_enum_i_32( + &self, + callback: impl FnMut(&super::ReducerEventContext, &Result) + Send + 'static, + ) -> InsertResultSimpleEnumI32CallbackId; + /// Cancel a callback previously registered by [`Self::on_insert_result_simple_enum_i_32`], + /// causing it not to run in the future. + fn remove_on_insert_result_simple_enum_i_32(&self, callback: InsertResultSimpleEnumI32CallbackId); +} + +impl insert_result_simple_enum_i_32 for super::RemoteReducers { + fn insert_result_simple_enum_i_32(&self, r: Result) -> __sdk::Result<()> { + self.imp + .call_reducer("insert_result_simple_enum_i32", InsertResultSimpleEnumI32Args { r }) + } + fn on_insert_result_simple_enum_i_32( + &self, + mut callback: impl FnMut(&super::ReducerEventContext, &Result) + Send + 'static, + ) -> InsertResultSimpleEnumI32CallbackId { + InsertResultSimpleEnumI32CallbackId(self.imp.on_reducer( + "insert_result_simple_enum_i32", + Box::new(move |ctx: &super::ReducerEventContext| { + let super::ReducerEventContext { + event: + __sdk::ReducerEvent { + reducer: super::Reducer::InsertResultSimpleEnumI32 { r }, + .. + }, + .. + } = ctx + else { + unreachable!() + }; + callback(ctx, r) + }), + )) + } + fn remove_on_insert_result_simple_enum_i_32(&self, callback: InsertResultSimpleEnumI32CallbackId) { + self.imp.remove_on_reducer("insert_result_simple_enum_i32", callback.0) + } +} + +#[allow(non_camel_case_types)] +#[doc(hidden)] +/// Extension trait for setting the call-flags for the reducer `insert_result_simple_enum_i32`. +/// +/// Implemented for [`super::SetReducerFlags`]. +/// +/// This type is currently unstable and may be removed without a major version bump. +pub trait set_flags_for_insert_result_simple_enum_i_32 { + /// Set the call-reducer flags for the reducer `insert_result_simple_enum_i32` to `flags`. + /// + /// This type is currently unstable and may be removed without a major version bump. + fn insert_result_simple_enum_i_32(&self, flags: __ws::CallReducerFlags); +} + +impl set_flags_for_insert_result_simple_enum_i_32 for super::SetReducerFlags { + fn insert_result_simple_enum_i_32(&self, flags: __ws::CallReducerFlags) { + self.imp.set_call_reducer_flags("insert_result_simple_enum_i32", flags); + } +} diff --git a/sdks/rust/tests/test-client/src/module_bindings/insert_result_string_i_32_reducer.rs b/sdks/rust/tests/test-client/src/module_bindings/insert_result_string_i_32_reducer.rs new file mode 100644 index 00000000000..bd344f18972 --- /dev/null +++ b/sdks/rust/tests/test-client/src/module_bindings/insert_result_string_i_32_reducer.rs @@ -0,0 +1,102 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#![allow(unused, clippy::all)] +use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; + +#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)] +#[sats(crate = __lib)] +pub(super) struct InsertResultStringI32Args { + pub r: Result, +} + +impl From for super::Reducer { + fn from(args: InsertResultStringI32Args) -> Self { + Self::InsertResultStringI32 { r: args.r } + } +} + +impl __sdk::InModule for InsertResultStringI32Args { + type Module = super::RemoteModule; +} + +pub struct InsertResultStringI32CallbackId(__sdk::CallbackId); + +#[allow(non_camel_case_types)] +/// Extension trait for access to the reducer `insert_result_string_i32`. +/// +/// Implemented for [`super::RemoteReducers`]. +pub trait insert_result_string_i_32 { + /// Request that the remote module invoke the reducer `insert_result_string_i32` to run as soon as possible. + /// + /// This method returns immediately, and errors only if we are unable to send the request. + /// The reducer will run asynchronously in the future, + /// and its status can be observed by listening for [`Self::on_insert_result_string_i_32`] callbacks. + fn insert_result_string_i_32(&self, r: Result) -> __sdk::Result<()>; + /// Register a callback to run whenever we are notified of an invocation of the reducer `insert_result_string_i32`. + /// + /// Callbacks should inspect the [`__sdk::ReducerEvent`] contained in the [`super::ReducerEventContext`] + /// to determine the reducer's status. + /// + /// The returned [`InsertResultStringI32CallbackId`] can be passed to [`Self::remove_on_insert_result_string_i_32`] + /// to cancel the callback. + fn on_insert_result_string_i_32( + &self, + callback: impl FnMut(&super::ReducerEventContext, &Result) + Send + 'static, + ) -> InsertResultStringI32CallbackId; + /// Cancel a callback previously registered by [`Self::on_insert_result_string_i_32`], + /// causing it not to run in the future. + fn remove_on_insert_result_string_i_32(&self, callback: InsertResultStringI32CallbackId); +} + +impl insert_result_string_i_32 for super::RemoteReducers { + fn insert_result_string_i_32(&self, r: Result) -> __sdk::Result<()> { + self.imp + .call_reducer("insert_result_string_i32", InsertResultStringI32Args { r }) + } + fn on_insert_result_string_i_32( + &self, + mut callback: impl FnMut(&super::ReducerEventContext, &Result) + Send + 'static, + ) -> InsertResultStringI32CallbackId { + InsertResultStringI32CallbackId(self.imp.on_reducer( + "insert_result_string_i32", + Box::new(move |ctx: &super::ReducerEventContext| { + let super::ReducerEventContext { + event: + __sdk::ReducerEvent { + reducer: super::Reducer::InsertResultStringI32 { r }, + .. + }, + .. + } = ctx + else { + unreachable!() + }; + callback(ctx, r) + }), + )) + } + fn remove_on_insert_result_string_i_32(&self, callback: InsertResultStringI32CallbackId) { + self.imp.remove_on_reducer("insert_result_string_i32", callback.0) + } +} + +#[allow(non_camel_case_types)] +#[doc(hidden)] +/// Extension trait for setting the call-flags for the reducer `insert_result_string_i32`. +/// +/// Implemented for [`super::SetReducerFlags`]. +/// +/// This type is currently unstable and may be removed without a major version bump. +pub trait set_flags_for_insert_result_string_i_32 { + /// Set the call-reducer flags for the reducer `insert_result_string_i32` to `flags`. + /// + /// This type is currently unstable and may be removed without a major version bump. + fn insert_result_string_i_32(&self, flags: __ws::CallReducerFlags); +} + +impl set_flags_for_insert_result_string_i_32 for super::SetReducerFlags { + fn insert_result_string_i_32(&self, flags: __ws::CallReducerFlags) { + self.imp.set_call_reducer_flags("insert_result_string_i32", flags); + } +} diff --git a/sdks/rust/tests/test-client/src/module_bindings/insert_result_vec_i_32_string_reducer.rs b/sdks/rust/tests/test-client/src/module_bindings/insert_result_vec_i_32_string_reducer.rs new file mode 100644 index 00000000000..0423867f021 --- /dev/null +++ b/sdks/rust/tests/test-client/src/module_bindings/insert_result_vec_i_32_string_reducer.rs @@ -0,0 +1,102 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#![allow(unused, clippy::all)] +use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; + +#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)] +#[sats(crate = __lib)] +pub(super) struct InsertResultVecI32StringArgs { + pub r: Result, String>, +} + +impl From for super::Reducer { + fn from(args: InsertResultVecI32StringArgs) -> Self { + Self::InsertResultVecI32String { r: args.r } + } +} + +impl __sdk::InModule for InsertResultVecI32StringArgs { + type Module = super::RemoteModule; +} + +pub struct InsertResultVecI32StringCallbackId(__sdk::CallbackId); + +#[allow(non_camel_case_types)] +/// Extension trait for access to the reducer `insert_result_vec_i32_string`. +/// +/// Implemented for [`super::RemoteReducers`]. +pub trait insert_result_vec_i_32_string { + /// Request that the remote module invoke the reducer `insert_result_vec_i32_string` to run as soon as possible. + /// + /// This method returns immediately, and errors only if we are unable to send the request. + /// The reducer will run asynchronously in the future, + /// and its status can be observed by listening for [`Self::on_insert_result_vec_i_32_string`] callbacks. + fn insert_result_vec_i_32_string(&self, r: Result, String>) -> __sdk::Result<()>; + /// Register a callback to run whenever we are notified of an invocation of the reducer `insert_result_vec_i32_string`. + /// + /// Callbacks should inspect the [`__sdk::ReducerEvent`] contained in the [`super::ReducerEventContext`] + /// to determine the reducer's status. + /// + /// The returned [`InsertResultVecI32StringCallbackId`] can be passed to [`Self::remove_on_insert_result_vec_i_32_string`] + /// to cancel the callback. + fn on_insert_result_vec_i_32_string( + &self, + callback: impl FnMut(&super::ReducerEventContext, &Result, String>) + Send + 'static, + ) -> InsertResultVecI32StringCallbackId; + /// Cancel a callback previously registered by [`Self::on_insert_result_vec_i_32_string`], + /// causing it not to run in the future. + fn remove_on_insert_result_vec_i_32_string(&self, callback: InsertResultVecI32StringCallbackId); +} + +impl insert_result_vec_i_32_string for super::RemoteReducers { + fn insert_result_vec_i_32_string(&self, r: Result, String>) -> __sdk::Result<()> { + self.imp + .call_reducer("insert_result_vec_i32_string", InsertResultVecI32StringArgs { r }) + } + fn on_insert_result_vec_i_32_string( + &self, + mut callback: impl FnMut(&super::ReducerEventContext, &Result, String>) + Send + 'static, + ) -> InsertResultVecI32StringCallbackId { + InsertResultVecI32StringCallbackId(self.imp.on_reducer( + "insert_result_vec_i32_string", + Box::new(move |ctx: &super::ReducerEventContext| { + let super::ReducerEventContext { + event: + __sdk::ReducerEvent { + reducer: super::Reducer::InsertResultVecI32String { r }, + .. + }, + .. + } = ctx + else { + unreachable!() + }; + callback(ctx, r) + }), + )) + } + fn remove_on_insert_result_vec_i_32_string(&self, callback: InsertResultVecI32StringCallbackId) { + self.imp.remove_on_reducer("insert_result_vec_i32_string", callback.0) + } +} + +#[allow(non_camel_case_types)] +#[doc(hidden)] +/// Extension trait for setting the call-flags for the reducer `insert_result_vec_i32_string`. +/// +/// Implemented for [`super::SetReducerFlags`]. +/// +/// This type is currently unstable and may be removed without a major version bump. +pub trait set_flags_for_insert_result_vec_i_32_string { + /// Set the call-reducer flags for the reducer `insert_result_vec_i32_string` to `flags`. + /// + /// This type is currently unstable and may be removed without a major version bump. + fn insert_result_vec_i_32_string(&self, flags: __ws::CallReducerFlags); +} + +impl set_flags_for_insert_result_vec_i_32_string for super::SetReducerFlags { + fn insert_result_vec_i_32_string(&self, flags: __ws::CallReducerFlags) { + self.imp.set_call_reducer_flags("insert_result_vec_i32_string", flags); + } +} diff --git a/sdks/rust/tests/test-client/src/module_bindings/mod.rs b/sdks/rust/tests/test-client/src/module_bindings/mod.rs index a3fd6ab9c2f..b2ce77a4731 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/mod.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/mod.rs @@ -1,7 +1,7 @@ // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE // WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. -// This was generated using spacetimedb cli version 1.8.0 (commit 798b1c7909306e832723f507f7a3c97d6abc610d). +// This was generated using spacetimedb cli version 1.10.0 (commit b5f3ce8c2dad6817d52ac14a03ea49bf638a2e17). #![allow(unused, clippy::all)] use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; @@ -117,6 +117,12 @@ pub mod insert_pk_u_32_two_reducer; pub mod insert_pk_u_64_reducer; pub mod insert_pk_u_8_reducer; pub mod insert_primitives_as_strings_reducer; +pub mod insert_result_every_primitive_struct_string_reducer; +pub mod insert_result_i_32_string_reducer; +pub mod insert_result_identity_string_reducer; +pub mod insert_result_simple_enum_i_32_reducer; +pub mod insert_result_string_i_32_reducer; +pub mod insert_result_vec_i_32_string_reducer; pub mod insert_table_holds_table_reducer; pub mod insert_unique_bool_reducer; pub mod insert_unique_connection_id_reducer; @@ -262,6 +268,18 @@ pub mod pk_u_64_table; pub mod pk_u_64_type; pub mod pk_u_8_table; pub mod pk_u_8_type; +pub mod result_every_primitive_struct_string_table; +pub mod result_every_primitive_struct_string_type; +pub mod result_i_32_string_table; +pub mod result_i_32_string_type; +pub mod result_identity_string_table; +pub mod result_identity_string_type; +pub mod result_simple_enum_i_32_table; +pub mod result_simple_enum_i_32_type; +pub mod result_string_i_32_table; +pub mod result_string_i_32_type; +pub mod result_vec_i_32_string_table; +pub mod result_vec_i_32_string_type; pub mod scheduled_table_table; pub mod scheduled_table_type; pub mod send_scheduled_message_reducer; @@ -595,6 +613,25 @@ pub use insert_pk_u_8_reducer::{insert_pk_u_8, set_flags_for_insert_pk_u_8, Inse pub use insert_primitives_as_strings_reducer::{ insert_primitives_as_strings, set_flags_for_insert_primitives_as_strings, InsertPrimitivesAsStringsCallbackId, }; +pub use insert_result_every_primitive_struct_string_reducer::{ + insert_result_every_primitive_struct_string, set_flags_for_insert_result_every_primitive_struct_string, + InsertResultEveryPrimitiveStructStringCallbackId, +}; +pub use insert_result_i_32_string_reducer::{ + insert_result_i_32_string, set_flags_for_insert_result_i_32_string, InsertResultI32StringCallbackId, +}; +pub use insert_result_identity_string_reducer::{ + insert_result_identity_string, set_flags_for_insert_result_identity_string, InsertResultIdentityStringCallbackId, +}; +pub use insert_result_simple_enum_i_32_reducer::{ + insert_result_simple_enum_i_32, set_flags_for_insert_result_simple_enum_i_32, InsertResultSimpleEnumI32CallbackId, +}; +pub use insert_result_string_i_32_reducer::{ + insert_result_string_i_32, set_flags_for_insert_result_string_i_32, InsertResultStringI32CallbackId, +}; +pub use insert_result_vec_i_32_string_reducer::{ + insert_result_vec_i_32_string, set_flags_for_insert_result_vec_i_32_string, InsertResultVecI32StringCallbackId, +}; pub use insert_table_holds_table_reducer::{ insert_table_holds_table, set_flags_for_insert_table_holds_table, InsertTableHoldsTableCallbackId, }; @@ -780,6 +817,18 @@ pub use pk_u_64_table::*; pub use pk_u_64_type::PkU64; pub use pk_u_8_table::*; pub use pk_u_8_type::PkU8; +pub use result_every_primitive_struct_string_table::*; +pub use result_every_primitive_struct_string_type::ResultEveryPrimitiveStructString; +pub use result_i_32_string_table::*; +pub use result_i_32_string_type::ResultI32String; +pub use result_identity_string_table::*; +pub use result_identity_string_type::ResultIdentityString; +pub use result_simple_enum_i_32_table::*; +pub use result_simple_enum_i_32_type::ResultSimpleEnumI32; +pub use result_string_i_32_table::*; +pub use result_string_i_32_type::ResultStringI32; +pub use result_vec_i_32_string_table::*; +pub use result_vec_i_32_string_type::ResultVecI32String; pub use scheduled_table_table::*; pub use scheduled_table_type::ScheduledTable; pub use send_scheduled_message_reducer::{ @@ -1290,6 +1339,24 @@ pub enum Reducer { InsertPrimitivesAsStrings { s: EveryPrimitiveStruct, }, + InsertResultEveryPrimitiveStructString { + r: Result, + }, + InsertResultI32String { + r: Result, + }, + InsertResultIdentityString { + r: Result<__sdk::Identity, String>, + }, + InsertResultSimpleEnumI32 { + r: Result, + }, + InsertResultStringI32 { + r: Result, + }, + InsertResultVecI32String { + r: Result, String>, + }, InsertTableHoldsTable { a: OneU8, b: VecU8, @@ -1694,6 +1761,12 @@ impl __sdk::Reducer for Reducer { Reducer::InsertPkU64 { .. } => "insert_pk_u64", Reducer::InsertPkU8 { .. } => "insert_pk_u8", Reducer::InsertPrimitivesAsStrings { .. } => "insert_primitives_as_strings", + Reducer::InsertResultEveryPrimitiveStructString { .. } => "insert_result_every_primitive_struct_string", + Reducer::InsertResultI32String { .. } => "insert_result_i32_string", + Reducer::InsertResultIdentityString { .. } => "insert_result_identity_string", + Reducer::InsertResultSimpleEnumI32 { .. } => "insert_result_simple_enum_i32", + Reducer::InsertResultStringI32 { .. } => "insert_result_string_i32", + Reducer::InsertResultVecI32String { .. } => "insert_result_vec_i32_string", Reducer::InsertTableHoldsTable { .. } => "insert_table_holds_table", Reducer::InsertUniqueBool { .. } => "insert_unique_bool", Reducer::InsertUniqueConnectionId { .. } => "insert_unique_connection_id", @@ -2304,6 +2377,32 @@ impl TryFrom<__ws::ReducerCallInfo<__ws::BsatnFormat>> for Reducer { insert_primitives_as_strings_reducer::InsertPrimitivesAsStringsArgs, >("insert_primitives_as_strings", &value.args)? .into()), + "insert_result_every_primitive_struct_string" => { + Ok(__sdk::parse_reducer_args::< + insert_result_every_primitive_struct_string_reducer::InsertResultEveryPrimitiveStructStringArgs, + >("insert_result_every_primitive_struct_string", &value.args)? + .into()) + } + "insert_result_i32_string" => Ok(__sdk::parse_reducer_args::< + insert_result_i_32_string_reducer::InsertResultI32StringArgs, + >("insert_result_i32_string", &value.args)? + .into()), + "insert_result_identity_string" => Ok(__sdk::parse_reducer_args::< + insert_result_identity_string_reducer::InsertResultIdentityStringArgs, + >("insert_result_identity_string", &value.args)? + .into()), + "insert_result_simple_enum_i32" => Ok(__sdk::parse_reducer_args::< + insert_result_simple_enum_i_32_reducer::InsertResultSimpleEnumI32Args, + >("insert_result_simple_enum_i32", &value.args)? + .into()), + "insert_result_string_i32" => Ok(__sdk::parse_reducer_args::< + insert_result_string_i_32_reducer::InsertResultStringI32Args, + >("insert_result_string_i32", &value.args)? + .into()), + "insert_result_vec_i32_string" => Ok(__sdk::parse_reducer_args::< + insert_result_vec_i_32_string_reducer::InsertResultVecI32StringArgs, + >("insert_result_vec_i32_string", &value.args)? + .into()), "insert_table_holds_table" => Ok(__sdk::parse_reducer_args::< insert_table_holds_table_reducer::InsertTableHoldsTableArgs, >("insert_table_holds_table", &value.args)? @@ -2822,6 +2921,12 @@ pub struct DbUpdate { pk_u_32_two: __sdk::TableUpdate, pk_u_64: __sdk::TableUpdate, pk_u_8: __sdk::TableUpdate, + result_every_primitive_struct_string: __sdk::TableUpdate, + result_i_32_string: __sdk::TableUpdate, + result_identity_string: __sdk::TableUpdate, + result_simple_enum_i_32: __sdk::TableUpdate, + result_string_i_32: __sdk::TableUpdate, + result_vec_i_32_string: __sdk::TableUpdate, scheduled_table: __sdk::TableUpdate, table_holds_table: __sdk::TableUpdate, unique_bool: __sdk::TableUpdate, @@ -3032,6 +3137,24 @@ impl TryFrom<__ws::DatabaseUpdate<__ws::BsatnFormat>> for DbUpdate { .pk_u_64 .append(pk_u_64_table::parse_table_update(table_update)?), "pk_u8" => db_update.pk_u_8.append(pk_u_8_table::parse_table_update(table_update)?), + "result_every_primitive_struct_string" => db_update.result_every_primitive_struct_string.append( + result_every_primitive_struct_string_table::parse_table_update(table_update)?, + ), + "result_i32_string" => db_update + .result_i_32_string + .append(result_i_32_string_table::parse_table_update(table_update)?), + "result_identity_string" => db_update + .result_identity_string + .append(result_identity_string_table::parse_table_update(table_update)?), + "result_simple_enum_i32" => db_update + .result_simple_enum_i_32 + .append(result_simple_enum_i_32_table::parse_table_update(table_update)?), + "result_string_i32" => db_update + .result_string_i_32 + .append(result_string_i_32_table::parse_table_update(table_update)?), + "result_vec_i32_string" => db_update + .result_vec_i_32_string + .append(result_vec_i_32_string_table::parse_table_update(table_update)?), "scheduled_table" => db_update .scheduled_table .append(scheduled_table_table::parse_table_update(table_update)?), @@ -3282,6 +3405,20 @@ impl __sdk::DbUpdate for DbUpdate { diff.pk_u_8 = cache .apply_diff_to_table::("pk_u8", &self.pk_u_8) .with_updates_by_pk(|row| &row.n); + diff.result_every_primitive_struct_string = cache.apply_diff_to_table::( + "result_every_primitive_struct_string", + &self.result_every_primitive_struct_string, + ); + diff.result_i_32_string = + cache.apply_diff_to_table::("result_i32_string", &self.result_i_32_string); + diff.result_identity_string = + cache.apply_diff_to_table::("result_identity_string", &self.result_identity_string); + diff.result_simple_enum_i_32 = + cache.apply_diff_to_table::("result_simple_enum_i32", &self.result_simple_enum_i_32); + diff.result_string_i_32 = + cache.apply_diff_to_table::("result_string_i32", &self.result_string_i_32); + diff.result_vec_i_32_string = + cache.apply_diff_to_table::("result_vec_i32_string", &self.result_vec_i_32_string); diff.scheduled_table = cache .apply_diff_to_table::("scheduled_table", &self.scheduled_table) .with_updates_by_pk(|row| &row.scheduled_id); @@ -3401,6 +3538,12 @@ pub struct AppliedDiff<'r> { pk_u_32_two: __sdk::TableAppliedDiff<'r, PkU32Two>, pk_u_64: __sdk::TableAppliedDiff<'r, PkU64>, pk_u_8: __sdk::TableAppliedDiff<'r, PkU8>, + result_every_primitive_struct_string: __sdk::TableAppliedDiff<'r, ResultEveryPrimitiveStructString>, + result_i_32_string: __sdk::TableAppliedDiff<'r, ResultI32String>, + result_identity_string: __sdk::TableAppliedDiff<'r, ResultIdentityString>, + result_simple_enum_i_32: __sdk::TableAppliedDiff<'r, ResultSimpleEnumI32>, + result_string_i_32: __sdk::TableAppliedDiff<'r, ResultStringI32>, + result_vec_i_32_string: __sdk::TableAppliedDiff<'r, ResultVecI32String>, scheduled_table: __sdk::TableAppliedDiff<'r, ScheduledTable>, table_holds_table: __sdk::TableAppliedDiff<'r, TableHoldsTable>, unique_bool: __sdk::TableAppliedDiff<'r, UniqueBool>, @@ -3532,6 +3675,28 @@ impl<'r> __sdk::AppliedDiff<'r> for AppliedDiff<'r> { callbacks.invoke_table_row_callbacks::("pk_u32_two", &self.pk_u_32_two, event); callbacks.invoke_table_row_callbacks::("pk_u64", &self.pk_u_64, event); callbacks.invoke_table_row_callbacks::("pk_u8", &self.pk_u_8, event); + callbacks.invoke_table_row_callbacks::( + "result_every_primitive_struct_string", + &self.result_every_primitive_struct_string, + event, + ); + callbacks.invoke_table_row_callbacks::("result_i32_string", &self.result_i_32_string, event); + callbacks.invoke_table_row_callbacks::( + "result_identity_string", + &self.result_identity_string, + event, + ); + callbacks.invoke_table_row_callbacks::( + "result_simple_enum_i32", + &self.result_simple_enum_i_32, + event, + ); + callbacks.invoke_table_row_callbacks::("result_string_i32", &self.result_string_i_32, event); + callbacks.invoke_table_row_callbacks::( + "result_vec_i32_string", + &self.result_vec_i_32_string, + event, + ); callbacks.invoke_table_row_callbacks::("scheduled_table", &self.scheduled_table, event); callbacks.invoke_table_row_callbacks::("table_holds_table", &self.table_holds_table, event); callbacks.invoke_table_row_callbacks::("unique_bool", &self.unique_bool, event); @@ -4365,6 +4530,12 @@ impl __sdk::SpacetimeModule for RemoteModule { pk_u_32_two_table::register_table(client_cache); pk_u_64_table::register_table(client_cache); pk_u_8_table::register_table(client_cache); + result_every_primitive_struct_string_table::register_table(client_cache); + result_i_32_string_table::register_table(client_cache); + result_identity_string_table::register_table(client_cache); + result_simple_enum_i_32_table::register_table(client_cache); + result_string_i_32_table::register_table(client_cache); + result_vec_i_32_string_table::register_table(client_cache); scheduled_table_table::register_table(client_cache); table_holds_table_table::register_table(client_cache); unique_bool_table::register_table(client_cache); diff --git a/sdks/rust/tests/test-client/src/module_bindings/result_every_primitive_struct_string_table.rs b/sdks/rust/tests/test-client/src/module_bindings/result_every_primitive_struct_string_table.rs new file mode 100644 index 00000000000..39f27548639 --- /dev/null +++ b/sdks/rust/tests/test-client/src/module_bindings/result_every_primitive_struct_string_table.rs @@ -0,0 +1,99 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#![allow(unused, clippy::all)] +use super::every_primitive_struct_type::EveryPrimitiveStruct; +use super::result_every_primitive_struct_string_type::ResultEveryPrimitiveStructString; +use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; + +/// Table handle for the table `result_every_primitive_struct_string`. +/// +/// Obtain a handle from the [`ResultEveryPrimitiveStructStringTableAccess::result_every_primitive_struct_string`] method on [`super::RemoteTables`], +/// like `ctx.db.result_every_primitive_struct_string()`. +/// +/// Users are encouraged not to explicitly reference this type, +/// but to directly chain method calls, +/// like `ctx.db.result_every_primitive_struct_string().on_insert(...)`. +pub struct ResultEveryPrimitiveStructStringTableHandle<'ctx> { + imp: __sdk::TableHandle, + ctx: std::marker::PhantomData<&'ctx super::RemoteTables>, +} + +#[allow(non_camel_case_types)] +/// Extension trait for access to the table `result_every_primitive_struct_string`. +/// +/// Implemented for [`super::RemoteTables`]. +pub trait ResultEveryPrimitiveStructStringTableAccess { + #[allow(non_snake_case)] + /// Obtain a [`ResultEveryPrimitiveStructStringTableHandle`], which mediates access to the table `result_every_primitive_struct_string`. + fn result_every_primitive_struct_string(&self) -> ResultEveryPrimitiveStructStringTableHandle<'_>; +} + +impl ResultEveryPrimitiveStructStringTableAccess for super::RemoteTables { + fn result_every_primitive_struct_string(&self) -> ResultEveryPrimitiveStructStringTableHandle<'_> { + ResultEveryPrimitiveStructStringTableHandle { + imp: self + .imp + .get_table::("result_every_primitive_struct_string"), + ctx: std::marker::PhantomData, + } + } +} + +pub struct ResultEveryPrimitiveStructStringInsertCallbackId(__sdk::CallbackId); +pub struct ResultEveryPrimitiveStructStringDeleteCallbackId(__sdk::CallbackId); + +impl<'ctx> __sdk::Table for ResultEveryPrimitiveStructStringTableHandle<'ctx> { + type Row = ResultEveryPrimitiveStructString; + type EventContext = super::EventContext; + + fn count(&self) -> u64 { + self.imp.count() + } + fn iter(&self) -> impl Iterator + '_ { + self.imp.iter() + } + + type InsertCallbackId = ResultEveryPrimitiveStructStringInsertCallbackId; + + fn on_insert( + &self, + callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static, + ) -> ResultEveryPrimitiveStructStringInsertCallbackId { + ResultEveryPrimitiveStructStringInsertCallbackId(self.imp.on_insert(Box::new(callback))) + } + + fn remove_on_insert(&self, callback: ResultEveryPrimitiveStructStringInsertCallbackId) { + self.imp.remove_on_insert(callback.0) + } + + type DeleteCallbackId = ResultEveryPrimitiveStructStringDeleteCallbackId; + + fn on_delete( + &self, + callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static, + ) -> ResultEveryPrimitiveStructStringDeleteCallbackId { + ResultEveryPrimitiveStructStringDeleteCallbackId(self.imp.on_delete(Box::new(callback))) + } + + fn remove_on_delete(&self, callback: ResultEveryPrimitiveStructStringDeleteCallbackId) { + self.imp.remove_on_delete(callback.0) + } +} + +#[doc(hidden)] +pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { + let _table = + client_cache.get_or_make_table::("result_every_primitive_struct_string"); +} + +#[doc(hidden)] +pub(super) fn parse_table_update( + raw_updates: __ws::TableUpdate<__ws::BsatnFormat>, +) -> __sdk::Result<__sdk::TableUpdate> { + __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { + __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") + .with_cause(e) + .into() + }) +} diff --git a/sdks/rust/tests/test-client/src/module_bindings/result_every_primitive_struct_string_type.rs b/sdks/rust/tests/test-client/src/module_bindings/result_every_primitive_struct_string_type.rs new file mode 100644 index 00000000000..27dd840464a --- /dev/null +++ b/sdks/rust/tests/test-client/src/module_bindings/result_every_primitive_struct_string_type.rs @@ -0,0 +1,17 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#![allow(unused, clippy::all)] +use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; + +use super::every_primitive_struct_type::EveryPrimitiveStruct; + +#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)] +#[sats(crate = __lib)] +pub struct ResultEveryPrimitiveStructString { + pub r: Result, +} + +impl __sdk::InModule for ResultEveryPrimitiveStructString { + type Module = super::RemoteModule; +} diff --git a/sdks/rust/tests/test-client/src/module_bindings/result_i_32_string_table.rs b/sdks/rust/tests/test-client/src/module_bindings/result_i_32_string_table.rs new file mode 100644 index 00000000000..b18d8c228a1 --- /dev/null +++ b/sdks/rust/tests/test-client/src/module_bindings/result_i_32_string_table.rs @@ -0,0 +1,95 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#![allow(unused, clippy::all)] +use super::result_i_32_string_type::ResultI32String; +use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; + +/// Table handle for the table `result_i32_string`. +/// +/// Obtain a handle from the [`ResultI32StringTableAccess::result_i_32_string`] method on [`super::RemoteTables`], +/// like `ctx.db.result_i_32_string()`. +/// +/// Users are encouraged not to explicitly reference this type, +/// but to directly chain method calls, +/// like `ctx.db.result_i_32_string().on_insert(...)`. +pub struct ResultI32StringTableHandle<'ctx> { + imp: __sdk::TableHandle, + ctx: std::marker::PhantomData<&'ctx super::RemoteTables>, +} + +#[allow(non_camel_case_types)] +/// Extension trait for access to the table `result_i32_string`. +/// +/// Implemented for [`super::RemoteTables`]. +pub trait ResultI32StringTableAccess { + #[allow(non_snake_case)] + /// Obtain a [`ResultI32StringTableHandle`], which mediates access to the table `result_i32_string`. + fn result_i_32_string(&self) -> ResultI32StringTableHandle<'_>; +} + +impl ResultI32StringTableAccess for super::RemoteTables { + fn result_i_32_string(&self) -> ResultI32StringTableHandle<'_> { + ResultI32StringTableHandle { + imp: self.imp.get_table::("result_i32_string"), + ctx: std::marker::PhantomData, + } + } +} + +pub struct ResultI32StringInsertCallbackId(__sdk::CallbackId); +pub struct ResultI32StringDeleteCallbackId(__sdk::CallbackId); + +impl<'ctx> __sdk::Table for ResultI32StringTableHandle<'ctx> { + type Row = ResultI32String; + type EventContext = super::EventContext; + + fn count(&self) -> u64 { + self.imp.count() + } + fn iter(&self) -> impl Iterator + '_ { + self.imp.iter() + } + + type InsertCallbackId = ResultI32StringInsertCallbackId; + + fn on_insert( + &self, + callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static, + ) -> ResultI32StringInsertCallbackId { + ResultI32StringInsertCallbackId(self.imp.on_insert(Box::new(callback))) + } + + fn remove_on_insert(&self, callback: ResultI32StringInsertCallbackId) { + self.imp.remove_on_insert(callback.0) + } + + type DeleteCallbackId = ResultI32StringDeleteCallbackId; + + fn on_delete( + &self, + callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static, + ) -> ResultI32StringDeleteCallbackId { + ResultI32StringDeleteCallbackId(self.imp.on_delete(Box::new(callback))) + } + + fn remove_on_delete(&self, callback: ResultI32StringDeleteCallbackId) { + self.imp.remove_on_delete(callback.0) + } +} + +#[doc(hidden)] +pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { + let _table = client_cache.get_or_make_table::("result_i32_string"); +} + +#[doc(hidden)] +pub(super) fn parse_table_update( + raw_updates: __ws::TableUpdate<__ws::BsatnFormat>, +) -> __sdk::Result<__sdk::TableUpdate> { + __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { + __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") + .with_cause(e) + .into() + }) +} diff --git a/sdks/rust/tests/test-client/src/module_bindings/result_i_32_string_type.rs b/sdks/rust/tests/test-client/src/module_bindings/result_i_32_string_type.rs new file mode 100644 index 00000000000..8eb0d4c5856 --- /dev/null +++ b/sdks/rust/tests/test-client/src/module_bindings/result_i_32_string_type.rs @@ -0,0 +1,15 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#![allow(unused, clippy::all)] +use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; + +#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)] +#[sats(crate = __lib)] +pub struct ResultI32String { + pub r: Result, +} + +impl __sdk::InModule for ResultI32String { + type Module = super::RemoteModule; +} diff --git a/sdks/rust/tests/test-client/src/module_bindings/result_identity_string_table.rs b/sdks/rust/tests/test-client/src/module_bindings/result_identity_string_table.rs new file mode 100644 index 00000000000..8a3d9d78b3e --- /dev/null +++ b/sdks/rust/tests/test-client/src/module_bindings/result_identity_string_table.rs @@ -0,0 +1,95 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#![allow(unused, clippy::all)] +use super::result_identity_string_type::ResultIdentityString; +use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; + +/// Table handle for the table `result_identity_string`. +/// +/// Obtain a handle from the [`ResultIdentityStringTableAccess::result_identity_string`] method on [`super::RemoteTables`], +/// like `ctx.db.result_identity_string()`. +/// +/// Users are encouraged not to explicitly reference this type, +/// but to directly chain method calls, +/// like `ctx.db.result_identity_string().on_insert(...)`. +pub struct ResultIdentityStringTableHandle<'ctx> { + imp: __sdk::TableHandle, + ctx: std::marker::PhantomData<&'ctx super::RemoteTables>, +} + +#[allow(non_camel_case_types)] +/// Extension trait for access to the table `result_identity_string`. +/// +/// Implemented for [`super::RemoteTables`]. +pub trait ResultIdentityStringTableAccess { + #[allow(non_snake_case)] + /// Obtain a [`ResultIdentityStringTableHandle`], which mediates access to the table `result_identity_string`. + fn result_identity_string(&self) -> ResultIdentityStringTableHandle<'_>; +} + +impl ResultIdentityStringTableAccess for super::RemoteTables { + fn result_identity_string(&self) -> ResultIdentityStringTableHandle<'_> { + ResultIdentityStringTableHandle { + imp: self.imp.get_table::("result_identity_string"), + ctx: std::marker::PhantomData, + } + } +} + +pub struct ResultIdentityStringInsertCallbackId(__sdk::CallbackId); +pub struct ResultIdentityStringDeleteCallbackId(__sdk::CallbackId); + +impl<'ctx> __sdk::Table for ResultIdentityStringTableHandle<'ctx> { + type Row = ResultIdentityString; + type EventContext = super::EventContext; + + fn count(&self) -> u64 { + self.imp.count() + } + fn iter(&self) -> impl Iterator + '_ { + self.imp.iter() + } + + type InsertCallbackId = ResultIdentityStringInsertCallbackId; + + fn on_insert( + &self, + callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static, + ) -> ResultIdentityStringInsertCallbackId { + ResultIdentityStringInsertCallbackId(self.imp.on_insert(Box::new(callback))) + } + + fn remove_on_insert(&self, callback: ResultIdentityStringInsertCallbackId) { + self.imp.remove_on_insert(callback.0) + } + + type DeleteCallbackId = ResultIdentityStringDeleteCallbackId; + + fn on_delete( + &self, + callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static, + ) -> ResultIdentityStringDeleteCallbackId { + ResultIdentityStringDeleteCallbackId(self.imp.on_delete(Box::new(callback))) + } + + fn remove_on_delete(&self, callback: ResultIdentityStringDeleteCallbackId) { + self.imp.remove_on_delete(callback.0) + } +} + +#[doc(hidden)] +pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { + let _table = client_cache.get_or_make_table::("result_identity_string"); +} + +#[doc(hidden)] +pub(super) fn parse_table_update( + raw_updates: __ws::TableUpdate<__ws::BsatnFormat>, +) -> __sdk::Result<__sdk::TableUpdate> { + __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { + __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") + .with_cause(e) + .into() + }) +} diff --git a/sdks/rust/tests/test-client/src/module_bindings/result_identity_string_type.rs b/sdks/rust/tests/test-client/src/module_bindings/result_identity_string_type.rs new file mode 100644 index 00000000000..e242fbc4d06 --- /dev/null +++ b/sdks/rust/tests/test-client/src/module_bindings/result_identity_string_type.rs @@ -0,0 +1,15 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#![allow(unused, clippy::all)] +use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; + +#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)] +#[sats(crate = __lib)] +pub struct ResultIdentityString { + pub r: Result<__sdk::Identity, String>, +} + +impl __sdk::InModule for ResultIdentityString { + type Module = super::RemoteModule; +} diff --git a/sdks/rust/tests/test-client/src/module_bindings/result_simple_enum_i_32_table.rs b/sdks/rust/tests/test-client/src/module_bindings/result_simple_enum_i_32_table.rs new file mode 100644 index 00000000000..4c2a65d9f66 --- /dev/null +++ b/sdks/rust/tests/test-client/src/module_bindings/result_simple_enum_i_32_table.rs @@ -0,0 +1,96 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#![allow(unused, clippy::all)] +use super::result_simple_enum_i_32_type::ResultSimpleEnumI32; +use super::simple_enum_type::SimpleEnum; +use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; + +/// Table handle for the table `result_simple_enum_i32`. +/// +/// Obtain a handle from the [`ResultSimpleEnumI32TableAccess::result_simple_enum_i_32`] method on [`super::RemoteTables`], +/// like `ctx.db.result_simple_enum_i_32()`. +/// +/// Users are encouraged not to explicitly reference this type, +/// but to directly chain method calls, +/// like `ctx.db.result_simple_enum_i_32().on_insert(...)`. +pub struct ResultSimpleEnumI32TableHandle<'ctx> { + imp: __sdk::TableHandle, + ctx: std::marker::PhantomData<&'ctx super::RemoteTables>, +} + +#[allow(non_camel_case_types)] +/// Extension trait for access to the table `result_simple_enum_i32`. +/// +/// Implemented for [`super::RemoteTables`]. +pub trait ResultSimpleEnumI32TableAccess { + #[allow(non_snake_case)] + /// Obtain a [`ResultSimpleEnumI32TableHandle`], which mediates access to the table `result_simple_enum_i32`. + fn result_simple_enum_i_32(&self) -> ResultSimpleEnumI32TableHandle<'_>; +} + +impl ResultSimpleEnumI32TableAccess for super::RemoteTables { + fn result_simple_enum_i_32(&self) -> ResultSimpleEnumI32TableHandle<'_> { + ResultSimpleEnumI32TableHandle { + imp: self.imp.get_table::("result_simple_enum_i32"), + ctx: std::marker::PhantomData, + } + } +} + +pub struct ResultSimpleEnumI32InsertCallbackId(__sdk::CallbackId); +pub struct ResultSimpleEnumI32DeleteCallbackId(__sdk::CallbackId); + +impl<'ctx> __sdk::Table for ResultSimpleEnumI32TableHandle<'ctx> { + type Row = ResultSimpleEnumI32; + type EventContext = super::EventContext; + + fn count(&self) -> u64 { + self.imp.count() + } + fn iter(&self) -> impl Iterator + '_ { + self.imp.iter() + } + + type InsertCallbackId = ResultSimpleEnumI32InsertCallbackId; + + fn on_insert( + &self, + callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static, + ) -> ResultSimpleEnumI32InsertCallbackId { + ResultSimpleEnumI32InsertCallbackId(self.imp.on_insert(Box::new(callback))) + } + + fn remove_on_insert(&self, callback: ResultSimpleEnumI32InsertCallbackId) { + self.imp.remove_on_insert(callback.0) + } + + type DeleteCallbackId = ResultSimpleEnumI32DeleteCallbackId; + + fn on_delete( + &self, + callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static, + ) -> ResultSimpleEnumI32DeleteCallbackId { + ResultSimpleEnumI32DeleteCallbackId(self.imp.on_delete(Box::new(callback))) + } + + fn remove_on_delete(&self, callback: ResultSimpleEnumI32DeleteCallbackId) { + self.imp.remove_on_delete(callback.0) + } +} + +#[doc(hidden)] +pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { + let _table = client_cache.get_or_make_table::("result_simple_enum_i32"); +} + +#[doc(hidden)] +pub(super) fn parse_table_update( + raw_updates: __ws::TableUpdate<__ws::BsatnFormat>, +) -> __sdk::Result<__sdk::TableUpdate> { + __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { + __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") + .with_cause(e) + .into() + }) +} diff --git a/sdks/rust/tests/test-client/src/module_bindings/result_simple_enum_i_32_type.rs b/sdks/rust/tests/test-client/src/module_bindings/result_simple_enum_i_32_type.rs new file mode 100644 index 00000000000..e5a4725035d --- /dev/null +++ b/sdks/rust/tests/test-client/src/module_bindings/result_simple_enum_i_32_type.rs @@ -0,0 +1,17 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#![allow(unused, clippy::all)] +use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; + +use super::simple_enum_type::SimpleEnum; + +#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)] +#[sats(crate = __lib)] +pub struct ResultSimpleEnumI32 { + pub r: Result, +} + +impl __sdk::InModule for ResultSimpleEnumI32 { + type Module = super::RemoteModule; +} diff --git a/sdks/rust/tests/test-client/src/module_bindings/result_string_i_32_table.rs b/sdks/rust/tests/test-client/src/module_bindings/result_string_i_32_table.rs new file mode 100644 index 00000000000..ea6b2c3c1aa --- /dev/null +++ b/sdks/rust/tests/test-client/src/module_bindings/result_string_i_32_table.rs @@ -0,0 +1,95 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#![allow(unused, clippy::all)] +use super::result_string_i_32_type::ResultStringI32; +use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; + +/// Table handle for the table `result_string_i32`. +/// +/// Obtain a handle from the [`ResultStringI32TableAccess::result_string_i_32`] method on [`super::RemoteTables`], +/// like `ctx.db.result_string_i_32()`. +/// +/// Users are encouraged not to explicitly reference this type, +/// but to directly chain method calls, +/// like `ctx.db.result_string_i_32().on_insert(...)`. +pub struct ResultStringI32TableHandle<'ctx> { + imp: __sdk::TableHandle, + ctx: std::marker::PhantomData<&'ctx super::RemoteTables>, +} + +#[allow(non_camel_case_types)] +/// Extension trait for access to the table `result_string_i32`. +/// +/// Implemented for [`super::RemoteTables`]. +pub trait ResultStringI32TableAccess { + #[allow(non_snake_case)] + /// Obtain a [`ResultStringI32TableHandle`], which mediates access to the table `result_string_i32`. + fn result_string_i_32(&self) -> ResultStringI32TableHandle<'_>; +} + +impl ResultStringI32TableAccess for super::RemoteTables { + fn result_string_i_32(&self) -> ResultStringI32TableHandle<'_> { + ResultStringI32TableHandle { + imp: self.imp.get_table::("result_string_i32"), + ctx: std::marker::PhantomData, + } + } +} + +pub struct ResultStringI32InsertCallbackId(__sdk::CallbackId); +pub struct ResultStringI32DeleteCallbackId(__sdk::CallbackId); + +impl<'ctx> __sdk::Table for ResultStringI32TableHandle<'ctx> { + type Row = ResultStringI32; + type EventContext = super::EventContext; + + fn count(&self) -> u64 { + self.imp.count() + } + fn iter(&self) -> impl Iterator + '_ { + self.imp.iter() + } + + type InsertCallbackId = ResultStringI32InsertCallbackId; + + fn on_insert( + &self, + callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static, + ) -> ResultStringI32InsertCallbackId { + ResultStringI32InsertCallbackId(self.imp.on_insert(Box::new(callback))) + } + + fn remove_on_insert(&self, callback: ResultStringI32InsertCallbackId) { + self.imp.remove_on_insert(callback.0) + } + + type DeleteCallbackId = ResultStringI32DeleteCallbackId; + + fn on_delete( + &self, + callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static, + ) -> ResultStringI32DeleteCallbackId { + ResultStringI32DeleteCallbackId(self.imp.on_delete(Box::new(callback))) + } + + fn remove_on_delete(&self, callback: ResultStringI32DeleteCallbackId) { + self.imp.remove_on_delete(callback.0) + } +} + +#[doc(hidden)] +pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { + let _table = client_cache.get_or_make_table::("result_string_i32"); +} + +#[doc(hidden)] +pub(super) fn parse_table_update( + raw_updates: __ws::TableUpdate<__ws::BsatnFormat>, +) -> __sdk::Result<__sdk::TableUpdate> { + __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { + __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") + .with_cause(e) + .into() + }) +} diff --git a/sdks/rust/tests/test-client/src/module_bindings/result_string_i_32_type.rs b/sdks/rust/tests/test-client/src/module_bindings/result_string_i_32_type.rs new file mode 100644 index 00000000000..463e9a8996b --- /dev/null +++ b/sdks/rust/tests/test-client/src/module_bindings/result_string_i_32_type.rs @@ -0,0 +1,15 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#![allow(unused, clippy::all)] +use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; + +#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)] +#[sats(crate = __lib)] +pub struct ResultStringI32 { + pub r: Result, +} + +impl __sdk::InModule for ResultStringI32 { + type Module = super::RemoteModule; +} diff --git a/sdks/rust/tests/test-client/src/module_bindings/result_vec_i_32_string_table.rs b/sdks/rust/tests/test-client/src/module_bindings/result_vec_i_32_string_table.rs new file mode 100644 index 00000000000..201e7e778d6 --- /dev/null +++ b/sdks/rust/tests/test-client/src/module_bindings/result_vec_i_32_string_table.rs @@ -0,0 +1,95 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#![allow(unused, clippy::all)] +use super::result_vec_i_32_string_type::ResultVecI32String; +use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; + +/// Table handle for the table `result_vec_i32_string`. +/// +/// Obtain a handle from the [`ResultVecI32StringTableAccess::result_vec_i_32_string`] method on [`super::RemoteTables`], +/// like `ctx.db.result_vec_i_32_string()`. +/// +/// Users are encouraged not to explicitly reference this type, +/// but to directly chain method calls, +/// like `ctx.db.result_vec_i_32_string().on_insert(...)`. +pub struct ResultVecI32StringTableHandle<'ctx> { + imp: __sdk::TableHandle, + ctx: std::marker::PhantomData<&'ctx super::RemoteTables>, +} + +#[allow(non_camel_case_types)] +/// Extension trait for access to the table `result_vec_i32_string`. +/// +/// Implemented for [`super::RemoteTables`]. +pub trait ResultVecI32StringTableAccess { + #[allow(non_snake_case)] + /// Obtain a [`ResultVecI32StringTableHandle`], which mediates access to the table `result_vec_i32_string`. + fn result_vec_i_32_string(&self) -> ResultVecI32StringTableHandle<'_>; +} + +impl ResultVecI32StringTableAccess for super::RemoteTables { + fn result_vec_i_32_string(&self) -> ResultVecI32StringTableHandle<'_> { + ResultVecI32StringTableHandle { + imp: self.imp.get_table::("result_vec_i32_string"), + ctx: std::marker::PhantomData, + } + } +} + +pub struct ResultVecI32StringInsertCallbackId(__sdk::CallbackId); +pub struct ResultVecI32StringDeleteCallbackId(__sdk::CallbackId); + +impl<'ctx> __sdk::Table for ResultVecI32StringTableHandle<'ctx> { + type Row = ResultVecI32String; + type EventContext = super::EventContext; + + fn count(&self) -> u64 { + self.imp.count() + } + fn iter(&self) -> impl Iterator + '_ { + self.imp.iter() + } + + type InsertCallbackId = ResultVecI32StringInsertCallbackId; + + fn on_insert( + &self, + callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static, + ) -> ResultVecI32StringInsertCallbackId { + ResultVecI32StringInsertCallbackId(self.imp.on_insert(Box::new(callback))) + } + + fn remove_on_insert(&self, callback: ResultVecI32StringInsertCallbackId) { + self.imp.remove_on_insert(callback.0) + } + + type DeleteCallbackId = ResultVecI32StringDeleteCallbackId; + + fn on_delete( + &self, + callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static, + ) -> ResultVecI32StringDeleteCallbackId { + ResultVecI32StringDeleteCallbackId(self.imp.on_delete(Box::new(callback))) + } + + fn remove_on_delete(&self, callback: ResultVecI32StringDeleteCallbackId) { + self.imp.remove_on_delete(callback.0) + } +} + +#[doc(hidden)] +pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { + let _table = client_cache.get_or_make_table::("result_vec_i32_string"); +} + +#[doc(hidden)] +pub(super) fn parse_table_update( + raw_updates: __ws::TableUpdate<__ws::BsatnFormat>, +) -> __sdk::Result<__sdk::TableUpdate> { + __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { + __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") + .with_cause(e) + .into() + }) +} diff --git a/sdks/rust/tests/test-client/src/module_bindings/result_vec_i_32_string_type.rs b/sdks/rust/tests/test-client/src/module_bindings/result_vec_i_32_string_type.rs new file mode 100644 index 00000000000..cc6c0a71b6c --- /dev/null +++ b/sdks/rust/tests/test-client/src/module_bindings/result_vec_i_32_string_type.rs @@ -0,0 +1,15 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#![allow(unused, clippy::all)] +use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; + +#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)] +#[sats(crate = __lib)] +pub struct ResultVecI32String { + pub r: Result, String>, +} + +impl __sdk::InModule for ResultVecI32String { + type Module = super::RemoteModule; +} diff --git a/smoketests/tests/pg_wire.py b/smoketests/tests/pg_wire.py index 24402e2ec9f..233bba1e3b5 100644 --- a/smoketests/tests/pg_wire.py +++ b/smoketests/tests/pg_wire.py @@ -92,6 +92,19 @@ class SqlFormat(Smoketest): ints: TInts, } +#[derive(Clone)] +#[spacetimedb::table(name = t_enums)] +pub struct TEnums { + bool_opt: Option, + bool_result: Result, + action: Action, +} + +#[spacetimedb::table(name = t_enums_tuple)] +pub struct TEnumsTuple { + tuple: TEnums, +} + #[spacetimedb::reducer] pub fn test(ctx: &ReducerContext) { let tuple = TInts { @@ -141,6 +154,15 @@ class SqlFormat(Smoketest): se: TSimpleEnum { id: 2, action: Action::Active }, ints, }); + + let tuple = TEnums { + bool_opt: Some(true), + bool_result: Ok(false), + action: Action::Active, + }; + + ctx.db.t_enums().insert(tuple.clone()); + ctx.db.t_enums_tuple().insert(TEnumsTuple { tuple }); } """ @@ -234,7 +256,19 @@ def test_sql_format(self): -----------------------------------+-------------------------------------+--------------------------------------------------------------------------------------------------------- {"id": 1, "color": {"Gray": 128}} | {"id": 2, "action": {"Active": {}}} | {"i8": -25, "i16": -3224, "i32": -23443, "i64": -2344353, "i128": -234434897853, "i256": -234434897853} (1 row)""") - + self.assertSql(token,"SELECT * FROM t_enums", """\ +bool_opt | bool_result | action +----------------+---------------+-------- + {"some": true} | {"ok": false} | Active +(1 row) +""") + self.assertSql(token,"SELECT * FROM t_enums_tuple", """\ +tuple +-------------------------------------------------------------------------------------- + {"bool_opt": {"some": true}, "bool_result": {"ok": false}, "action": {"Active": {}}} +(1 row) +""") + def test_sql_conn(self): """This test is designed to test connecting to the database and executing queries using `psycopg2`""" token = self.read_token() diff --git a/smoketests/tests/sql.py b/smoketests/tests/sql.py index c90d63c3661..1b33fbc5460 100644 --- a/smoketests/tests/sql.py +++ b/smoketests/tests/sql.py @@ -4,7 +4,7 @@ class SqlFormat(Smoketest): MODULE_CODE = """ use spacetimedb::sats::{i256, u256}; -use spacetimedb::{table, ConnectionId, Identity, ReducerContext, Table, Timestamp, TimeDuration}; +use spacetimedb::{table, ConnectionId, Identity, ReducerContext, Table, Timestamp, TimeDuration, SpacetimeType }; #[derive(Copy, Clone)] #[spacetimedb::table(name = t_ints)] @@ -57,6 +57,25 @@ class SqlFormat(Smoketest): tuple: TOthers } +#[derive(SpacetimeType, Debug, Clone, Copy)] +pub enum Action { + Inactive, + Active, +} + +#[derive(Clone)] +#[spacetimedb::table(name = t_enums)] +pub struct TEnums { + bool_opt: Option, + bool_result: Result, + action: Action, +} + +#[spacetimedb::table(name = t_enums_tuple)] +pub struct TEnumsTuple { + tuple: TEnums, +} + #[spacetimedb::reducer] pub fn test(ctx: &ReducerContext) { let tuple = TInts { @@ -94,6 +113,15 @@ class SqlFormat(Smoketest): }; ctx.db.t_others().insert(tuple.clone()); ctx.db.t_others_tuple().insert(TOthersTuple { tuple }); + + let tuple = TEnums { + bool_opt: Some(true), + bool_result: Ok(false), + action: Action::Active, + }; + + ctx.db.t_enums().insert(tuple.clone()); + ctx.db.t_enums_tuple().insert(TEnumsTuple { tuple }); } """ @@ -138,4 +166,14 @@ def test_sql_format(self): tuple ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- (bool = true, f32 = 594806.56, f64 = -3454353.345389043, str = "This is spacetimedb", bytes = 0x01020304050607, identity = 0x0000000000000000000000000000000000000000000000000000000000000001, connection_id = 0x00000000000000000000000000000000, timestamp = 1970-01-01T00:00:00+00:00, duration = +0.000000) +""") + self.assertSql("SELECT * FROM t_enums", """\ + bool_opt | bool_result | action +---------------+--------------+--------------- + (some = true) | (ok = false) | (Active = ()) +""") + self.assertSql("SELECT * FROM t_enums_tuple", """\ + tuple +-------------------------------------------------------------------------------- + (bool_opt = (some = true), bool_result = (ok = false), action = (Active = ())) """) From 581d4aebefa9afd14e63fe5e2a9e6b3f89852b7c Mon Sep 17 00:00:00 2001 From: Jason Larabie Date: Fri, 5 Dec 2025 18:45:39 -0800 Subject: [PATCH 2/3] Added Unreal Result type to support C++ and Blueprint via generation of new struct for each Result type like Option types, included full integration test as well. --- crates/codegen/src/unrealcpp.rs | 514 +++++++++++++++--- .../Public/BSATN/UESpacetimeDB.h | 56 ++ .../ModuleBindings/SpacetimeDBClient.g.cpp | 306 +++++++++++ ...esultEveryPrimitiveStructStringTable.g.cpp | 35 ++ .../Tables/ResultI32StringTable.g.cpp | 35 ++ .../Tables/ResultIdentityStringTable.g.cpp | 35 ++ .../Tables/ResultSimpleEnumI32Table.g.cpp | 35 ++ .../Tables/ResultStringI32Table.g.cpp | 35 ++ .../Tables/ResultVecI32StringTable.g.cpp | 35 ++ .../Tests/SpacetimeFullClientTests.cpp | 108 ++++ .../TestClient/Private/Tests/TestHandler.cpp | 72 +++ ...InsertResultEveryPrimitiveStructString.g.h | 55 ++ .../Reducers/InsertResultI32String.g.h | 54 ++ .../Reducers/InsertResultIdentityString.g.h | 55 ++ .../Reducers/InsertResultSimpleEnumI32.g.h | 55 ++ .../Reducers/InsertResultStringI32.g.h | 54 ++ .../Reducers/InsertResultVecI32String.g.h | 54 ++ ...ClientResultEveryPrimitiveStructString.g.h | 101 ++++ .../TestClientResultIdentityString.g.h | 101 ++++ .../Results/TestClientResultInt32String.g.h | 100 ++++ .../TestClientResultSimpleEnumInt32.g.h | 101 ++++ .../Results/TestClientResultStringInt32.g.h | 100 ++++ .../TestClientResultVecInt32String.g.h | 100 ++++ .../ModuleBindings/SpacetimeDBClient.g.h | 322 ++++++++++- .../ResultEveryPrimitiveStructStringTable.g.h | 64 +++ .../Tables/ResultI32StringTable.g.h | 64 +++ .../Tables/ResultIdentityStringTable.g.h | 64 +++ .../Tables/ResultSimpleEnumI32Table.g.h | 64 +++ .../Tables/ResultStringI32Table.g.h | 64 +++ .../Tables/ResultVecI32StringTable.g.h | 64 +++ .../Types/EnumWithPayloadType.g.h | 2 +- .../ResultEveryPrimitiveStructStringType.g.h | 47 ++ .../Types/ResultI32StringType.g.h | 46 ++ .../Types/ResultIdentityStringType.g.h | 47 ++ .../Types/ResultSimpleEnumI32Type.g.h | 47 ++ .../Types/ResultStringI32Type.g.h | 46 ++ .../Types/ResultVecI32StringType.g.h | 46 ++ .../Public/Tests/SpacetimeFullClientTests.h | 6 + .../TestClient/Public/Tests/TestHandler.h | 20 + .../Public/Tests/UmbreallaHeaderTypes.h | 6 + .../Public/Tests/UmbreallaHeaderaTables.h | 6 + .../ModuleBindings/SpacetimeDBClient.g.h | 2 +- .../ModuleBindings/Types/ReturnEnumType.g.h | 2 +- sdks/unreal/tests/test.rs | 6 + 44 files changed, 3143 insertions(+), 88 deletions(-) create mode 100644 sdks/unreal/tests/TestClient/Source/TestClient/Private/ModuleBindings/Tables/ResultEveryPrimitiveStructStringTable.g.cpp create mode 100644 sdks/unreal/tests/TestClient/Source/TestClient/Private/ModuleBindings/Tables/ResultI32StringTable.g.cpp create mode 100644 sdks/unreal/tests/TestClient/Source/TestClient/Private/ModuleBindings/Tables/ResultIdentityStringTable.g.cpp create mode 100644 sdks/unreal/tests/TestClient/Source/TestClient/Private/ModuleBindings/Tables/ResultSimpleEnumI32Table.g.cpp create mode 100644 sdks/unreal/tests/TestClient/Source/TestClient/Private/ModuleBindings/Tables/ResultStringI32Table.g.cpp create mode 100644 sdks/unreal/tests/TestClient/Source/TestClient/Private/ModuleBindings/Tables/ResultVecI32StringTable.g.cpp create mode 100644 sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Reducers/InsertResultEveryPrimitiveStructString.g.h create mode 100644 sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Reducers/InsertResultI32String.g.h create mode 100644 sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Reducers/InsertResultIdentityString.g.h create mode 100644 sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Reducers/InsertResultSimpleEnumI32.g.h create mode 100644 sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Reducers/InsertResultStringI32.g.h create mode 100644 sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Reducers/InsertResultVecI32String.g.h create mode 100644 sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Results/TestClientResultEveryPrimitiveStructString.g.h create mode 100644 sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Results/TestClientResultIdentityString.g.h create mode 100644 sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Results/TestClientResultInt32String.g.h create mode 100644 sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Results/TestClientResultSimpleEnumInt32.g.h create mode 100644 sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Results/TestClientResultStringInt32.g.h create mode 100644 sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Results/TestClientResultVecInt32String.g.h create mode 100644 sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Tables/ResultEveryPrimitiveStructStringTable.g.h create mode 100644 sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Tables/ResultI32StringTable.g.h create mode 100644 sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Tables/ResultIdentityStringTable.g.h create mode 100644 sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Tables/ResultSimpleEnumI32Table.g.h create mode 100644 sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Tables/ResultStringI32Table.g.h create mode 100644 sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Tables/ResultVecI32StringTable.g.h create mode 100644 sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Types/ResultEveryPrimitiveStructStringType.g.h create mode 100644 sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Types/ResultI32StringType.g.h create mode 100644 sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Types/ResultIdentityStringType.g.h create mode 100644 sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Types/ResultSimpleEnumI32Type.g.h create mode 100644 sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Types/ResultStringI32Type.g.h create mode 100644 sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Types/ResultVecI32StringType.g.h diff --git a/crates/codegen/src/unrealcpp.rs b/crates/codegen/src/unrealcpp.rs index cd93321e458..0ddab050f5e 100644 --- a/crates/codegen/src/unrealcpp.rs +++ b/crates/codegen/src/unrealcpp.rs @@ -20,6 +20,7 @@ use std::collections::HashSet; use std::fmt::{self}; use std::ops::Deref; use std::path::Path; +use std::result; pub struct UnrealCpp<'opts> { pub module_name: &'opts str, @@ -766,7 +767,7 @@ impl Lang for UnrealCpp<'_> { let mut files: Vec = vec![]; // First, collect and generate all optional types - let optional_types = collect_optional_types(module); + let (optional_types, result_types) = collect_wrapper_types(module); for optional_name in optional_types { let module_name = &self.module_name; let module_name_pascal = module_name.to_case(Case::Pascal); @@ -780,6 +781,20 @@ impl Lang for UnrealCpp<'_> { }); } + for (ok_name, error_name) in result_types { + let module_name = &self.module_name; + let module_name_pascal = module_name.to_case(Case::Pascal); + let filename = format!( + "Source/{module_name}/Public/ModuleBindings/Results/{module_name_pascal}Result{ok_name}{error_name}.g.h" + ); + + let content = generate_result_type(&ok_name, &error_name, module, &self.get_api_macro(), self.module_name); + files.push(OutputFile { + filename, + code: content, + }); + } + // Generate the main SpacetimeDBClient file with proper manual includes let mut includes = HashSet::::new(); @@ -3869,33 +3884,49 @@ impl UnrealCppAutogen { // Helpers // --------------------------------------------------------------------------- -fn collect_optional_types(module: &ModuleDef) -> HashSet { +// Unified helper function to collect special wrapper types (optionals and results) +fn collect_wrapper_types(module: &ModuleDef) -> (HashSet, HashSet<(String, String)>) { let mut optional_types = HashSet::new(); + let mut result_types = HashSet::new(); - // Helper function to collect from a type - fn collect_from_type(module: &ModuleDef, ty: &AlgebraicTypeUse, out: &mut HashSet) { + // Helper function to recursively collect from a type + fn collect_from_type( + module: &ModuleDef, + ty: &AlgebraicTypeUse, + optional_types: &mut HashSet, + result_types: &mut HashSet<(String, String)>, + ) { match ty { AlgebraicTypeUse::Option(inner) => { // Generate the optional type name let optional_name = get_optional_type_name(module, inner); - out.insert(optional_name); + optional_types.insert(optional_name); // Recursively collect from inner type - collect_from_type(module, inner, out); + collect_from_type(module, inner, optional_types, result_types); + } + AlgebraicTypeUse::Result { ok_ty, err_ty } => { + // Generate the result type name components + let ok_name = get_type_name_for_result(module, ok_ty); + let err_name = get_type_name_for_result(module, err_ty); + result_types.insert((ok_name, err_name)); + // Recursively collect from both inner types + collect_from_type(module, ok_ty, optional_types, result_types); + collect_from_type(module, err_ty, optional_types, result_types); } AlgebraicTypeUse::Array(elem) => { - collect_from_type(module, elem, out); + collect_from_type(module, elem, optional_types, result_types); } AlgebraicTypeUse::Ref(r) => { - // Check if the referenced type contains optionals + // Check if the referenced type contains optionals or results match &module.typespace_for_generate()[*r] { AlgebraicTypeDef::Product(product) => { for (_, field_ty) in &product.elements { - collect_from_type(module, field_ty, out); + collect_from_type(module, field_ty, optional_types, result_types); } } AlgebraicTypeDef::Sum(sum) => { for (_, variant_ty) in &sum.variants { - collect_from_type(module, variant_ty, out); + collect_from_type(module, variant_ty, optional_types, result_types); } } _ => {} @@ -3909,7 +3940,7 @@ fn collect_optional_types(module: &ModuleDef) -> HashSet { for (_, product_type_ref) in iter_table_names_and_types(module) { let product_type = module.typespace_for_generate()[product_type_ref].as_product().unwrap(); for (_, field_ty) in &product_type.elements { - collect_from_type(module, field_ty, &mut optional_types); + collect_from_type(module, field_ty, &mut optional_types, &mut result_types); } } @@ -3918,12 +3949,12 @@ fn collect_optional_types(module: &ModuleDef) -> HashSet { match &module.typespace_for_generate()[typ.ty] { AlgebraicTypeDef::Product(product) => { for (_, field_ty) in &product.elements { - collect_from_type(module, field_ty, &mut optional_types); + collect_from_type(module, field_ty, &mut optional_types, &mut result_types); } } AlgebraicTypeDef::Sum(sum) => { for (_, variant_ty) in &sum.variants { - collect_from_type(module, variant_ty, &mut optional_types); + collect_from_type(module, variant_ty, &mut optional_types, &mut result_types); } } _ => {} @@ -3933,22 +3964,28 @@ fn collect_optional_types(module: &ModuleDef) -> HashSet { // Collect from reducer parameters for reducer in iter_reducers(module) { for (_, param_ty) in &reducer.params_for_generate.elements { - collect_from_type(module, param_ty, &mut optional_types); + collect_from_type(module, param_ty, &mut optional_types, &mut result_types); } } - // Collect from procedure parameters + // Collect from procedure parameters and return types for procedure in iter_procedures(module) { for (_, param_ty) in &procedure.params_for_generate.elements { - collect_from_type(module, param_ty, &mut optional_types); + collect_from_type(module, param_ty, &mut optional_types, &mut result_types); } - collect_from_type(module, &procedure.return_type_for_generate, &mut optional_types); + collect_from_type( + module, + &procedure.return_type_for_generate, + &mut optional_types, + &mut result_types, + ); } - optional_types + + (optional_types, result_types) } // Helper function to get C++ type for array elements in optional arrays -fn get_cpp_type_for_array_element(elem_type_str: &str, _: &ModuleDef, module_name: &str) -> String { +fn get_cpp_type_for_array_element(module: &ModuleDef, elem_type_str: &str, module_name: &str) -> String { match elem_type_str { "Bool" => "bool".to_string(), "I8" | "Int8" => "int8".to_string(), @@ -3977,7 +4014,25 @@ fn get_cpp_type_for_array_element(elem_type_str: &str, _: &ModuleDef, module_nam format!("F{module_name_pascal}OptionalInt32") } _ => { - format!("E{elem_type_str}Type") + let is_enum = module.types().any(|type_def| { + let type_name = type_def + .name + .name_segments() + .last() + .map(|id| id.deref().to_string()) + .unwrap_or_else(|| "Unnamed".to_string()); + type_name == elem_type_str + && matches!( + module.typespace_for_generate()[type_def.ty], + AlgebraicTypeDef::PlainEnum(_) + ) + }); + + if is_enum { + format!("E{elem_type_str}Type") + } else { + format!("F{elem_type_str}Type") + } } } } @@ -4013,6 +4068,10 @@ fn get_array_element_type_name(module: &ModuleDef, elem: &AlgebraicTypeUse) -> S // Handle optional elements in arrays like Vec> get_optional_type_name(module, nested_inner) } + AlgebraicTypeUse::Result { ok_ty, err_ty } => { + // Handle result elements in arrays like Vec> + get_result_type_name(module, ok_ty, err_ty) + } _ => "Unknown".to_string(), } } @@ -4057,17 +4116,17 @@ fn get_optional_type_name(module: &ModuleDef, inner: &AlgebraicTypeUse) -> Strin let inner_optional_name = get_optional_type_name(module, nested_inner); format!("Optional{inner_optional_name}") } + AlgebraicTypeUse::Result { ok_ty, err_ty } => { + let result_name = get_result_type_name(module, ok_ty, err_ty); + format!("Optional{result_name}") + } _ => "OptionalUnknown".to_string(), } } -// Generate the content for an optional type file -fn generate_optional_type(optional_name: &str, module: &ModuleDef, api_macro: &str, module_name: &str) -> String { - // Extract the inner type from the optional name - let inner_type_str = optional_name.strip_prefix("Optional").unwrap_or(optional_name); - - // Determine the C++ type for the inner value - let cpp_inner_type = match inner_type_str { +// Helper function to determine C++ type from type name string for result types +fn determine_cpp_type_for_result(type_name: &str, module: &ModuleDef, module_name: &str) -> String { + match type_name { "Bool" => "bool".to_string(), "Int8" => "int8".to_string(), "UInt8" => "uint8".to_string(), @@ -4089,34 +4148,39 @@ fn generate_optional_type(optional_name: &str, module: &ModuleDef, api_macro: &s "Timestamp" => "FSpacetimeDBTimestamp".to_string(), "TimeDuration" => "FSpacetimeDBTimeDuration".to_string(), "ScheduleAt" => "FSpacetimeDBScheduleAt".to_string(), - "Array" => "TArray".to_string(), // Fallback for generic array type (should not be used with new system) - _ if inner_type_str.starts_with("Optional") => { - // Handle nested optionals like OptionalOptionalString + "Unit" => "FSpacetimeDBUnit".to_string(), + _ if type_name.starts_with("Optional") => { + // Handle optional types like OptionalString let module_name_pascal = module_name.to_case(Case::Pascal); - format!("F{module_name_pascal}{inner_type_str}") + format!("F{module_name_pascal}{type_name}") } - _ if inner_type_str.starts_with("VecOptional") => { + _ if type_name.starts_with("VecOptional") => { // Handle specific optional array types like OptionalVecOptionalI32, OptionalVecOptionalString, etc. - let elem_type_str = &inner_type_str[11..]; // Remove "VecOptional" prefix + let elem_type_str = &type_name[11..]; // Remove "VecOptional" prefix let module_name_pascal = module_name.to_case(Case::Pascal); format!("TArray") } - _ if inner_type_str.starts_with("Vec") => { - // Handle OptionalVecXxx -> should use TArray - let elem_type_str = &inner_type_str[3..]; // Remove "Vec" prefix - let cpp_elem_type = get_cpp_type_for_array_element(elem_type_str, module, module_name); + _ if type_name.starts_with("Vec") => { + // Handle array types like VecInt32 + let elem_type_str = &type_name[3..]; // Remove "Vec" prefix + let cpp_elem_type = get_cpp_type_for_array_element(module, elem_type_str, module_name); format!("TArray<{cpp_elem_type}>") } + _ if type_name.starts_with("Result") => { + // Handle nested result types + let module_name_pascal = module_name.to_case(Case::Pascal); + format!("F{module_name_pascal}{type_name}") + } _ => { // For custom types, check if it's an enum or struct let is_enum = module.types().any(|type_def| { - let type_name = type_def + let type_name_from_def = type_def .name .name_segments() .last() .map(|id| id.deref().to_string()) .unwrap_or_else(|| "Unnamed".to_string()); - type_name == inner_type_str + type_name_from_def == type_name && matches!( module.typespace_for_generate()[type_def.ty], AlgebraicTypeDef::PlainEnum(_) @@ -4124,45 +4188,98 @@ fn generate_optional_type(optional_name: &str, module: &ModuleDef, api_macro: &s }); if is_enum { - format!("E{inner_type_str}Type") + format!("E{type_name}Type") } else { - format!("F{inner_type_str}Type") + format!("F{type_name}Type") } } - }; + } +} - // Determine if we need extra includes - let mut extra_includes = vec![]; - match inner_type_str { +// Helper function to check if a type name is blueprintable +fn is_type_name_blueprintable(type_name: &str) -> bool { + match type_name { + // Non-blueprintable primitive types + "Int8" | "Int16" | "UInt16" | "UInt32" | "UInt64" => false, + + // Blueprintable types + "Bool" | "Int32" | "Int64" | "Float" | "Double" | "String" | "Identity" | "ConnectionId" | "Timestamp" + | "TimeDuration" | "ScheduleAt" | "Int128" | "UInt128" | "Int256" | "UInt256" | "Unit" => true, + + // Optional types - check the inner type + _ if type_name.starts_with("Optional") => { + let inner_type = &type_name[8..]; // Remove "Optional" prefix + is_type_name_blueprintable(inner_type) + } + + // Result types - both Ok and Err types must be blueprintable + // Parse ResultXXXYYY to extract both type names + _ if type_name.starts_with("Result") => { + // This is complex - we'd need to parse "ResultInt32String" into "Int32" and "String" + // For now, be conservative and return true since Result wrapper itself is a USTRUCT + // The individual fields will have their own blueprintable checks + true + } + + // Vec types - arrays are blueprintable if element is blueprintable + _ if type_name.starts_with("Vec") => { + let elem_type = &type_name[3..]; // Remove "Vec" prefix + is_type_name_blueprintable(elem_type) + } + + // Custom types (structs/enums) are always blueprintable + _ => true, + } +} + +// Helper function to add includes for a type name +fn add_includes_for_type_name(type_name: &str, includes: &mut Vec, module_name: &str) { + match type_name { "Identity" | "ConnectionId" | "Timestamp" | "TimeDuration" | "ScheduleAt" => { - extra_includes.push("Types/Builtins.h".to_string()); + includes.push("Types/Builtins.h".to_string()); } "Int128" | "UInt128" | "Int256" | "UInt256" => { - extra_includes.push("Types/LargeIntegers.h".to_string()); + includes.push("Types/LargeIntegers.h".to_string()); + } + "Unit" => { + includes.push("Types/UnitType.h".to_string()); } "String" | "Bool" | "Int8" | "UInt8" | "Int16" | "UInt16" | "Int32" | "UInt32" | "Int64" | "UInt64" - | "Float" | "Double" | "Array" => { + | "Float" | "Double" => { // Basic types, no extra includes needed } - _ if inner_type_str.starts_with("Vec") => { - // Not required + _ if type_name.starts_with("Vec") => { + // Array types - no extra include needed for TArray itself } - _ if inner_type_str.starts_with("OptionalVec") => { - // Not required - } - _ if inner_type_str.starts_with("Optional") => { + _ if type_name.starts_with("Optional") => { // Nested optional, need its header let module_name_pascal = module_name.to_case(Case::Pascal); - extra_includes.push(format!( - "ModuleBindings/Optionals/{module_name_pascal}{inner_type_str}.g.h" - )); + includes.push(format!("ModuleBindings/Optionals/{module_name_pascal}{type_name}.g.h")); } - _ if !inner_type_str.starts_with("Int") && !inner_type_str.starts_with("UInt") => { + _ if type_name.starts_with("Result") => { + // Nested result, need its header + let module_name_pascal = module_name.to_case(Case::Pascal); + includes.push(format!("ModuleBindings/Results/{module_name_pascal}{type_name}.g.h")); + } + _ if !type_name.starts_with("Int") && !type_name.starts_with("UInt") => { // Custom type, need its header - extra_includes.push(format!("ModuleBindings/Types/{inner_type_str}Type.g.h")); + includes.push(format!("ModuleBindings/Types/{type_name}Type.g.h")); } _ => {} } +} + +// Generate the content for an optional type file +fn generate_optional_type(optional_name: &str, module: &ModuleDef, api_macro: &str, module_name: &str) -> String { + // Extract the inner type from the optional name + let inner_type_str = optional_name.strip_prefix("Optional").unwrap_or(optional_name); + + // Determine the C++ type for the inner value + let cpp_inner_type = determine_cpp_type_for_result(inner_type_str, module, module_name); + + // Determine if we need extra includes + let mut extra_includes = vec![]; + add_includes_for_type_name(inner_type_str, &mut extra_includes, module_name); let extra_includes_refs: Vec<&str> = extra_includes.iter().map(|s| s.as_str()).collect(); let module_name_pascal = module_name.to_case(Case::Pascal); @@ -4187,26 +4304,7 @@ fn generate_optional_type(optional_name: &str, module: &ModuleDef, api_macro: &s // The actual value // Check if the type is blueprintable - let is_blueprintable = match inner_type_str { - "UInt16" | "UInt32" | "UInt64" => false, - _ if inner_type_str.starts_with("Vec") => { - // Check blueprintability of array element type for VecXxx types - let elem_type_str = &inner_type_str[3..]; // Remove "Vec" prefix - match elem_type_str { - "UInt16" | "UInt32" | "UInt64" => false, // Unsigned types are not blueprintable - _ => true, - } - } - _ if inner_type_str.starts_with("OptionalVec") => { - // Check blueprintability of array element type - let elem_type_str = &inner_type_str[11..]; // Remove "OptionalVec" prefix - match elem_type_str { - "U16" | "U32" | "U64" => false, // Unsigned types are not blueprintable - _ => true, - } - } - _ => true, - }; + let is_blueprintable = is_type_name_blueprintable(inner_type_str); if is_blueprintable { writeln!(output, "UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = \"SpacetimeDB\", meta = (EditCondition = \"bHasValue\"))"); @@ -4288,6 +4386,252 @@ fn generate_optional_type(optional_name: &str, module: &ModuleDef, api_macro: &s output.into_inner() } +// Get the name for a result type (e.g., "ResultStringString", "ResultInt32String") +fn get_result_type_name(module: &ModuleDef, ok_ty: &AlgebraicTypeUse, err_ty: &AlgebraicTypeUse) -> String { + let ok_name = get_type_name_for_result(module, ok_ty); + let err_name = get_type_name_for_result(module, err_ty); + format!("Result{ok_name}{err_name}") +} + +// Helper function to get the type name component for result types +fn get_type_name_for_result(module: &ModuleDef, ty: &AlgebraicTypeUse) -> String { + match ty { + AlgebraicTypeUse::Primitive(p) => match p { + PrimitiveType::Bool => "Bool".to_string(), + PrimitiveType::I8 => "Int8".to_string(), + PrimitiveType::U8 => "UInt8".to_string(), + PrimitiveType::I16 => "Int16".to_string(), + PrimitiveType::U16 => "UInt16".to_string(), + PrimitiveType::I32 => "Int32".to_string(), + PrimitiveType::U32 => "UInt32".to_string(), + PrimitiveType::I64 => "Int64".to_string(), + PrimitiveType::U64 => "UInt64".to_string(), + PrimitiveType::F32 => "Float".to_string(), + PrimitiveType::F64 => "Double".to_string(), + PrimitiveType::I128 => "Int128".to_string(), + PrimitiveType::U128 => "UInt128".to_string(), + PrimitiveType::I256 => "Int256".to_string(), + PrimitiveType::U256 => "UInt256".to_string(), + }, + AlgebraicTypeUse::String => "String".to_string(), + AlgebraicTypeUse::Identity => "Identity".to_string(), + AlgebraicTypeUse::ConnectionId => "ConnectionId".to_string(), + AlgebraicTypeUse::Timestamp => "Timestamp".to_string(), + AlgebraicTypeUse::TimeDuration => "TimeDuration".to_string(), + AlgebraicTypeUse::ScheduleAt => "ScheduleAt".to_string(), + AlgebraicTypeUse::Unit => "Unit".to_string(), + AlgebraicTypeUse::Array(elem) => { + // Generate specific array types based on element type + let elem_name = get_array_element_type_name(module, elem); + format!("Vec{elem_name}") + } + AlgebraicTypeUse::Ref(r) => type_ref_name(module, *r), + AlgebraicTypeUse::Option(inner) => { + // Handle optional types like Option + let inner_name = get_type_name_for_result(module, inner); + format!("Optional{inner_name}") + } + AlgebraicTypeUse::Result { ok_ty, err_ty } => { + // Handle nested results like Result, bool> + get_result_type_name(module, ok_ty, err_ty) + } + AlgebraicTypeUse::Never => "Never".to_string(), + } +} + +// Generate the content for a result type file +fn generate_result_type( + ok_type_name: &str, + err_type_name: &str, + module: &ModuleDef, + api_macro: &str, + module_name: &str, +) -> String { + // Determine the C++ type for the ok value + let cpp_ok_type = determine_cpp_type_for_result(ok_type_name, module, module_name); + + // Determine the C++ type for the err value + let cpp_err_type = determine_cpp_type_for_result(err_type_name, module, module_name); + + // Determine if we need extra includes + let mut extra_includes = vec![]; + add_includes_for_type_name(ok_type_name, &mut extra_includes, module_name); + add_includes_for_type_name(err_type_name, &mut extra_includes, module_name); + + let extra_includes_refs: Vec<&str> = extra_includes.iter().map(|s| s.as_str()).collect(); + let module_name_pascal = module_name.to_case(Case::Pascal); + let result_name = format!("Result{ok_type_name}{err_type_name}"); + let struct_name = format!("F{module_name_pascal}{result_name}"); + let header_name = format!("{module_name_pascal}{result_name}"); + let mut output = UnrealCppAutogen::new(&extra_includes_refs, &header_name, false); + + writeln!(output, "USTRUCT(BlueprintType)"); + writeln!(output, "struct {api_macro} {struct_name}"); + writeln!(output, "{{"); + output.indent(1); + writeln!(output, "GENERATED_BODY()"); + writeln!(output); + + // Is ok flag + writeln!( + output, + "UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = \"SpacetimeDB\")" + ); + writeln!(output, "bool bIsOk = false;"); + writeln!(output); + + // The ok value + let is_ok_blueprintable = is_type_name_blueprintable(ok_type_name); + if is_ok_blueprintable { + writeln!(output, "UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = \"SpacetimeDB\", meta = (EditCondition = \"bIsOk\"))"); + } else { + writeln!( + output, + "// NOTE: {cpp_ok_type} field not exposed to Blueprint due to non-blueprintable type" + ); + } + writeln!(output, "{cpp_ok_type} OkValue;"); + writeln!(output); + + // The err value + let is_err_blueprintable = is_type_name_blueprintable(err_type_name); + if is_err_blueprintable { + writeln!(output, "UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = \"SpacetimeDB\", meta = (EditCondition = \"!bIsOk\"))"); + } else { + writeln!( + output, + "// NOTE: {cpp_err_type} field not exposed to Blueprint due to non-blueprintable type" + ); + } + writeln!(output, "{cpp_err_type} ErrValue;"); + writeln!(output); + + // Constructors + writeln!(output, "{struct_name}() = default;"); + writeln!(output); + + // Ok constructor + writeln!(output, "static {struct_name} Ok(const {cpp_ok_type}& InValue)"); + writeln!(output, "{{"); + output.indent(1); + writeln!(output, "{struct_name} Result;"); + writeln!(output, "Result.bIsOk = true;"); + writeln!(output, "Result.OkValue = InValue;"); + writeln!(output, "return Result;"); + output.dedent(1); + writeln!(output, "}}"); + writeln!(output); + + // Err constructor + writeln!(output, "static {struct_name} Err(const {cpp_err_type}& InValue)"); + writeln!(output, "{{"); + output.indent(1); + writeln!(output, "{struct_name} Result;"); + writeln!(output, "Result.bIsOk = false;"); + writeln!(output, "Result.ErrValue = InValue;"); + writeln!(output, "return Result;"); + output.dedent(1); + writeln!(output, "}}"); + writeln!(output); + + // Helper methods + writeln!(output, "bool IsOk() const {{ return bIsOk; }}"); + writeln!(output, "bool IsErr() const {{ return !bIsOk; }}"); + writeln!(output); + + writeln!(output, "const {cpp_ok_type}& GetOk() const"); + writeln!(output, "{{"); + output.indent(1); + writeln!(output, "check(bIsOk);"); + writeln!(output, "return OkValue;"); + output.dedent(1); + writeln!(output, "}}"); + writeln!(output); + + writeln!(output, "const {cpp_err_type}& GetErr() const"); + writeln!(output, "{{"); + output.indent(1); + writeln!(output, "check(!bIsOk);"); + writeln!(output, "return ErrValue;"); + output.dedent(1); + writeln!(output, "}}"); + writeln!(output); + + // Operators + writeln!(output, "FORCEINLINE bool operator==(const {struct_name}& Other) const"); + writeln!(output, "{{"); + output.indent(1); + writeln!(output, "if (bIsOk != Other.bIsOk) return false;"); + writeln!(output, "if (bIsOk)"); + writeln!(output, "{{"); + output.indent(1); + writeln!(output, "return OkValue == Other.OkValue;"); + output.dedent(1); + writeln!(output, "}}"); + writeln!(output, "else"); + writeln!(output, "{{"); + output.indent(1); + writeln!(output, "return ErrValue == Other.ErrValue;"); + output.dedent(1); + writeln!(output, "}}"); + output.dedent(1); + writeln!(output, "}}"); + writeln!(output); + + writeln!(output, "FORCEINLINE bool operator!=(const {struct_name}& Other) const"); + writeln!(output, "{{"); + output.indent(1); + writeln!(output, "return !(*this == Other);"); + output.dedent(1); + writeln!(output, "}}"); + + output.dedent(1); + writeln!(output, "}};"); + writeln!(output); + + // Add GetTypeHash implementation + writeln!(output, "/**"); + writeln!(output, " * Custom hash function for {struct_name}."); + writeln!(output, " * Hashes the bIsOk flag and the appropriate value."); + writeln!(output, " * @param Result The {struct_name} instance to hash."); + writeln!(output, " * @return The combined hash value."); + writeln!(output, " */"); + writeln!(output, "FORCEINLINE uint32 GetTypeHash(const {struct_name}& Result)"); + writeln!(output, "{{"); + output.indent(1); + writeln!(output, "uint32 Hash = GetTypeHash(Result.bIsOk);"); + writeln!(output, "if (Result.bIsOk)"); + writeln!(output, "{{"); + output.indent(1); + writeln!(output, "Hash = HashCombine(Hash, GetTypeHash(Result.OkValue));"); + output.dedent(1); + writeln!(output, "}}"); + writeln!(output, "else"); + writeln!(output, "{{"); + output.indent(1); + writeln!(output, "Hash = HashCombine(Hash, GetTypeHash(Result.ErrValue));"); + output.dedent(1); + writeln!(output, "}}"); + writeln!(output, "return Hash;"); + output.dedent(1); + writeln!(output, "}}"); + writeln!(output); + + // BSATN serialization support + writeln!(output, "namespace UE::SpacetimeDB"); + writeln!(output, "{{"); + + writeln!(output, " UE_SPACETIMEDB_ENABLE_TARRAY({struct_name});"); + writeln!(output); + writeln!( + output, + " UE_SPACETIMEDB_RESULT({struct_name}, bIsOk, OkValue, ErrValue);" + ); + writeln!(output, "}}"); + + output.into_inner() +} + fn autogen_cpp_struct( module: &ModuleDef, name: &str, // Changed to &str @@ -5002,10 +5346,11 @@ fn cpp_ty_fmt_impl<'a>( // Result use the generated result types AlgebraicTypeUse::Result { ok_ty, err_ty } => { - let ok_type = cpp_ty_fmt_impl(module, ok_ty, module_name).to_string(); - let err_type = cpp_ty_fmt_impl(module, err_ty, module_name).to_string(); + let ok_name = get_type_name_for_result(module, ok_ty); + let err_name = get_type_name_for_result(module, err_ty); + let module_name_pascal = module_name.to_case(Case::Pascal); - write!(f, "FSpacetimeDBResult<{ok_type}, {err_type}>") + write!(f, "F{module_name_pascal}Result{ok_name}{err_name}") } AlgebraicTypeUse::Never => unreachable!("never type"), @@ -5076,7 +5421,10 @@ fn collect_includes_for_type( } Result { ok_ty, err_ty } => { // Add the result type header - out.insert("Types/Result.h".to_string()); + let result_name = get_result_type_name(module, ok_ty, err_ty); + let module_name_pascal = module_name.to_case(Case::Pascal); + let header = format!("ModuleBindings/Results/{module_name_pascal}{result_name}.g.h"); + out.insert(header); // Also collect includes for the ok and err types collect_includes_for_type(module, ok_ty, out, module_name); collect_includes_for_type(module, err_ty, out, module_name); diff --git a/sdks/unreal/src/SpacetimeDbSdk/Source/SpacetimeDbSdk/Public/BSATN/UESpacetimeDB.h b/sdks/unreal/src/SpacetimeDbSdk/Source/SpacetimeDbSdk/Public/BSATN/UESpacetimeDB.h index 2afc6b5313a..8b25806e282 100644 --- a/sdks/unreal/src/SpacetimeDbSdk/Source/SpacetimeDbSdk/Public/BSATN/UESpacetimeDB.h +++ b/sdks/unreal/src/SpacetimeDbSdk/Source/SpacetimeDbSdk/Public/BSATN/UESpacetimeDB.h @@ -682,6 +682,62 @@ namespace UE::SpacetimeDB { /** @} */ // end of CustomOptionalStructSerialization group + // ============================================================================= + // Custom Result struct Serialization + // ============================================================================= + /** + * @brief Helper macro to generate serialization for Blueprint compatible result structs + * @{ + * + * This macro creates serialize/deserialize specializations for a struct that + * mimics the behaviour of Result types by exposing an "is ok" boolean flag, + * an "ok" value field, and an "error" value field. + * + * @param StructType Name of the result wrapper struct + * @param IsOkField Name of the boolean member that signals if the result is ok + * @param OkValueField Name of the value member for the ok case + * @param ErrValueField Name of the value member for the error case + * + * Example usage: + * @code + * USTRUCT(BlueprintType) + * struct FResultStringBool { + * int32 OkValue; + * FString ErrorValue; + * bool bIsOk; + * }; + * + * namespace UE::SpacetimeDB { + * UE_SPACETIMEDB_RESULT(FResultStringBool, bIsOk, OkValue, ErrorValue); + * } + * @endcode + */ +#define UE_SPACETIMEDB_RESULT(StructType, IsOkField, OkValueField, ErrValueField) \ + template<> inline void serialize(UEWriter& w, const StructType& value) { \ + if (value.IsOkField) { \ + w.write_u8(0); /* ok tag */ \ + serialize(w, value.OkValueField); \ + } else { \ + w.write_u8(1); /* err tag */ \ + serialize(w, value.ErrValueField); \ + } \ + } \ + template<> inline StructType deserialize(UEReader& r) { \ + StructType result; \ + uint8_t tag = r.read_u8(); \ + if (tag == 0) { \ + result.IsOkField = true; \ + result.OkValueField = deserialize(r); \ + } else if (tag == 1) { \ + result.IsOkField = false; \ + result.ErrValueField = deserialize(r); \ + } else { \ + ensureMsgf(false, TEXT("Invalid result tag: %d"), tag); \ + return StructType(); \ + } \ + return result; \ + } + // ============================================================================= // UE Utility Type Serialization // ============================================================================= diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Private/ModuleBindings/SpacetimeDBClient.g.cpp b/sdks/unreal/tests/TestClient/Source/TestClient/Private/ModuleBindings/SpacetimeDBClient.g.cpp index 2ed8757fca7..45e8dd3f6d2 100644 --- a/sdks/unreal/tests/TestClient/Source/TestClient/Private/ModuleBindings/SpacetimeDBClient.g.cpp +++ b/sdks/unreal/tests/TestClient/Source/TestClient/Private/ModuleBindings/SpacetimeDBClient.g.cpp @@ -58,6 +58,12 @@ #include "ModuleBindings/Tables/PkU32TwoTable.g.h" #include "ModuleBindings/Tables/PkU64Table.g.h" #include "ModuleBindings/Tables/PkU8Table.g.h" +#include "ModuleBindings/Tables/ResultEveryPrimitiveStructStringTable.g.h" +#include "ModuleBindings/Tables/ResultI32StringTable.g.h" +#include "ModuleBindings/Tables/ResultIdentityStringTable.g.h" +#include "ModuleBindings/Tables/ResultSimpleEnumI32Table.g.h" +#include "ModuleBindings/Tables/ResultStringI32Table.g.h" +#include "ModuleBindings/Tables/ResultVecI32StringTable.g.h" #include "ModuleBindings/Tables/ScheduledTableTable.g.h" #include "ModuleBindings/Tables/TableHoldsTableTable.g.h" #include "ModuleBindings/Tables/UniqueBoolTable.g.h" @@ -701,6 +707,42 @@ static FReducer DecodeReducer(const FReducerEvent& Event) return FReducer::InsertPrimitivesAsStrings(Args); } + if (ReducerName == TEXT("insert_result_every_primitive_struct_string")) + { + FInsertResultEveryPrimitiveStructStringArgs Args = UE::SpacetimeDB::Deserialize(Event.ReducerCall.Args); + return FReducer::InsertResultEveryPrimitiveStructString(Args); + } + + if (ReducerName == TEXT("insert_result_i32_string")) + { + FInsertResultI32StringArgs Args = UE::SpacetimeDB::Deserialize(Event.ReducerCall.Args); + return FReducer::InsertResultI32String(Args); + } + + if (ReducerName == TEXT("insert_result_identity_string")) + { + FInsertResultIdentityStringArgs Args = UE::SpacetimeDB::Deserialize(Event.ReducerCall.Args); + return FReducer::InsertResultIdentityString(Args); + } + + if (ReducerName == TEXT("insert_result_simple_enum_i32")) + { + FInsertResultSimpleEnumI32Args Args = UE::SpacetimeDB::Deserialize(Event.ReducerCall.Args); + return FReducer::InsertResultSimpleEnumI32(Args); + } + + if (ReducerName == TEXT("insert_result_string_i32")) + { + FInsertResultStringI32Args Args = UE::SpacetimeDB::Deserialize(Event.ReducerCall.Args); + return FReducer::InsertResultStringI32(Args); + } + + if (ReducerName == TEXT("insert_result_vec_i32_string")) + { + FInsertResultVecI32StringArgs Args = UE::SpacetimeDB::Deserialize(Event.ReducerCall.Args); + return FReducer::InsertResultVecI32String(Args); + } + if (ReducerName == TEXT("insert_table_holds_table")) { FInsertTableHoldsTableArgs Args = UE::SpacetimeDB::Deserialize(Event.ReducerCall.Args); @@ -1258,6 +1300,12 @@ UDbConnection::UDbConnection(const FObjectInitializer& ObjectInitializer) : Supe RegisterTable(TEXT("pk_u32_two"), Db->PkU32Two); RegisterTable(TEXT("pk_u64"), Db->PkU64); RegisterTable(TEXT("pk_u8"), Db->PkU8); + RegisterTable(TEXT("result_every_primitive_struct_string"), Db->ResultEveryPrimitiveStructString); + RegisterTable(TEXT("result_i32_string"), Db->ResultI32String); + RegisterTable(TEXT("result_identity_string"), Db->ResultIdentityString); + RegisterTable(TEXT("result_simple_enum_i32"), Db->ResultSimpleEnumI32); + RegisterTable(TEXT("result_string_i32"), Db->ResultStringI32); + RegisterTable(TEXT("result_vec_i32_string"), Db->ResultVecI32String); RegisterTable(TEXT("scheduled_table"), Db->ScheduledTable); RegisterTable(TEXT("table_holds_table"), Db->TableHoldsTable); RegisterTable(TEXT("unique_bool"), Db->UniqueBool); @@ -1391,6 +1439,12 @@ void URemoteTables::Initialize() PkU32Two = NewObject(this); PkU64 = NewObject(this); PkU8 = NewObject(this); + ResultEveryPrimitiveStructString = NewObject(this); + ResultI32String = NewObject(this); + ResultIdentityString = NewObject(this); + ResultSimpleEnumI32 = NewObject(this); + ResultStringI32 = NewObject(this); + ResultVecI32String = NewObject(this); ScheduledTable = NewObject(this); TableHoldsTable = NewObject(this); UniqueBool = NewObject(this); @@ -1492,6 +1546,12 @@ void URemoteTables::Initialize() PkU32Two->PostInitialize(); PkU64->PostInitialize(); PkU8->PostInitialize(); + ResultEveryPrimitiveStructString->PostInitialize(); + ResultI32String->PostInitialize(); + ResultIdentityString->PostInitialize(); + ResultSimpleEnumI32->PostInitialize(); + ResultStringI32->PostInitialize(); + ResultVecI32String->PostInitialize(); ScheduledTable->PostInitialize(); TableHoldsTable->PostInitialize(); UniqueBool->PostInitialize(); @@ -1935,6 +1995,30 @@ void USetReducerFlags::InsertPrimitivesAsStrings(ECallReducerFlags Flag) { FlagMap.Add("InsertPrimitivesAsStrings", Flag); } +void USetReducerFlags::InsertResultEveryPrimitiveStructString(ECallReducerFlags Flag) +{ + FlagMap.Add("InsertResultEveryPrimitiveStructString", Flag); +} +void USetReducerFlags::InsertResultI32String(ECallReducerFlags Flag) +{ + FlagMap.Add("InsertResultI32String", Flag); +} +void USetReducerFlags::InsertResultIdentityString(ECallReducerFlags Flag) +{ + FlagMap.Add("InsertResultIdentityString", Flag); +} +void USetReducerFlags::InsertResultSimpleEnumI32(ECallReducerFlags Flag) +{ + FlagMap.Add("InsertResultSimpleEnumI32", Flag); +} +void USetReducerFlags::InsertResultStringI32(ECallReducerFlags Flag) +{ + FlagMap.Add("InsertResultStringI32", Flag); +} +void USetReducerFlags::InsertResultVecI32String(ECallReducerFlags Flag) +{ + FlagMap.Add("InsertResultVecI32String", Flag); +} void USetReducerFlags::InsertTableHoldsTable(ECallReducerFlags Flag) { FlagMap.Add("InsertTableHoldsTable", Flag); @@ -5177,6 +5261,180 @@ bool URemoteReducers::InvokeInsertPrimitivesAsStrings(const FReducerEventContext return true; } +void URemoteReducers::InsertResultEveryPrimitiveStructString(const FTestClientResultEveryPrimitiveStructString& R) +{ + if (!Conn) + { + UE_LOG(LogTemp, Error, TEXT("SpacetimeDB connection is null")); + return; + } + + Conn->CallReducerTyped(TEXT("insert_result_every_primitive_struct_string"), FInsertResultEveryPrimitiveStructStringArgs(R), SetCallReducerFlags); +} + +bool URemoteReducers::InvokeInsertResultEveryPrimitiveStructString(const FReducerEventContext& Context, const UInsertResultEveryPrimitiveStructStringReducer* Args) +{ + if (!OnInsertResultEveryPrimitiveStructString.IsBound()) + { + // Handle unhandled reducer error + if (InternalOnUnhandledReducerError.IsBound()) + { + // TODO: Check Context.Event.Status for Failed/OutOfEnergy cases + // For now, just broadcast any error + InternalOnUnhandledReducerError.Broadcast(Context, TEXT("No handler registered for InsertResultEveryPrimitiveStructString")); + } + return false; + } + + OnInsertResultEveryPrimitiveStructString.Broadcast(Context, Args->R); + return true; +} + +void URemoteReducers::InsertResultI32String(const FTestClientResultInt32String& R) +{ + if (!Conn) + { + UE_LOG(LogTemp, Error, TEXT("SpacetimeDB connection is null")); + return; + } + + Conn->CallReducerTyped(TEXT("insert_result_i32_string"), FInsertResultI32StringArgs(R), SetCallReducerFlags); +} + +bool URemoteReducers::InvokeInsertResultI32String(const FReducerEventContext& Context, const UInsertResultI32StringReducer* Args) +{ + if (!OnInsertResultI32String.IsBound()) + { + // Handle unhandled reducer error + if (InternalOnUnhandledReducerError.IsBound()) + { + // TODO: Check Context.Event.Status for Failed/OutOfEnergy cases + // For now, just broadcast any error + InternalOnUnhandledReducerError.Broadcast(Context, TEXT("No handler registered for InsertResultI32String")); + } + return false; + } + + OnInsertResultI32String.Broadcast(Context, Args->R); + return true; +} + +void URemoteReducers::InsertResultIdentityString(const FTestClientResultIdentityString& R) +{ + if (!Conn) + { + UE_LOG(LogTemp, Error, TEXT("SpacetimeDB connection is null")); + return; + } + + Conn->CallReducerTyped(TEXT("insert_result_identity_string"), FInsertResultIdentityStringArgs(R), SetCallReducerFlags); +} + +bool URemoteReducers::InvokeInsertResultIdentityString(const FReducerEventContext& Context, const UInsertResultIdentityStringReducer* Args) +{ + if (!OnInsertResultIdentityString.IsBound()) + { + // Handle unhandled reducer error + if (InternalOnUnhandledReducerError.IsBound()) + { + // TODO: Check Context.Event.Status for Failed/OutOfEnergy cases + // For now, just broadcast any error + InternalOnUnhandledReducerError.Broadcast(Context, TEXT("No handler registered for InsertResultIdentityString")); + } + return false; + } + + OnInsertResultIdentityString.Broadcast(Context, Args->R); + return true; +} + +void URemoteReducers::InsertResultSimpleEnumI32(const FTestClientResultSimpleEnumInt32& R) +{ + if (!Conn) + { + UE_LOG(LogTemp, Error, TEXT("SpacetimeDB connection is null")); + return; + } + + Conn->CallReducerTyped(TEXT("insert_result_simple_enum_i32"), FInsertResultSimpleEnumI32Args(R), SetCallReducerFlags); +} + +bool URemoteReducers::InvokeInsertResultSimpleEnumI32(const FReducerEventContext& Context, const UInsertResultSimpleEnumI32Reducer* Args) +{ + if (!OnInsertResultSimpleEnumI32.IsBound()) + { + // Handle unhandled reducer error + if (InternalOnUnhandledReducerError.IsBound()) + { + // TODO: Check Context.Event.Status for Failed/OutOfEnergy cases + // For now, just broadcast any error + InternalOnUnhandledReducerError.Broadcast(Context, TEXT("No handler registered for InsertResultSimpleEnumI32")); + } + return false; + } + + OnInsertResultSimpleEnumI32.Broadcast(Context, Args->R); + return true; +} + +void URemoteReducers::InsertResultStringI32(const FTestClientResultStringInt32& R) +{ + if (!Conn) + { + UE_LOG(LogTemp, Error, TEXT("SpacetimeDB connection is null")); + return; + } + + Conn->CallReducerTyped(TEXT("insert_result_string_i32"), FInsertResultStringI32Args(R), SetCallReducerFlags); +} + +bool URemoteReducers::InvokeInsertResultStringI32(const FReducerEventContext& Context, const UInsertResultStringI32Reducer* Args) +{ + if (!OnInsertResultStringI32.IsBound()) + { + // Handle unhandled reducer error + if (InternalOnUnhandledReducerError.IsBound()) + { + // TODO: Check Context.Event.Status for Failed/OutOfEnergy cases + // For now, just broadcast any error + InternalOnUnhandledReducerError.Broadcast(Context, TEXT("No handler registered for InsertResultStringI32")); + } + return false; + } + + OnInsertResultStringI32.Broadcast(Context, Args->R); + return true; +} + +void URemoteReducers::InsertResultVecI32String(const FTestClientResultVecInt32String& R) +{ + if (!Conn) + { + UE_LOG(LogTemp, Error, TEXT("SpacetimeDB connection is null")); + return; + } + + Conn->CallReducerTyped(TEXT("insert_result_vec_i32_string"), FInsertResultVecI32StringArgs(R), SetCallReducerFlags); +} + +bool URemoteReducers::InvokeInsertResultVecI32String(const FReducerEventContext& Context, const UInsertResultVecI32StringReducer* Args) +{ + if (!OnInsertResultVecI32String.IsBound()) + { + // Handle unhandled reducer error + if (InternalOnUnhandledReducerError.IsBound()) + { + // TODO: Check Context.Event.Status for Failed/OutOfEnergy cases + // For now, just broadcast any error + InternalOnUnhandledReducerError.Broadcast(Context, TEXT("No handler registered for InsertResultVecI32String")); + } + return false; + } + + OnInsertResultVecI32String.Broadcast(Context, Args->R); + return true; +} + void URemoteReducers::InsertTableHoldsTable(const FOneU8Type& A, const FVecU8Type& B) { if (!Conn) @@ -8429,6 +8687,54 @@ void UDbConnection::ReducerEvent(const FReducerEvent& Event) Reducers->InvokeInsertPrimitivesAsStrings(Context, Reducer); return; } + if (ReducerName == TEXT("insert_result_every_primitive_struct_string")) + { + FInsertResultEveryPrimitiveStructStringArgs Args = ReducerEvent.Reducer.GetAsInsertResultEveryPrimitiveStructString(); + UInsertResultEveryPrimitiveStructStringReducer* Reducer = NewObject(); + Reducer->R = Args.R; + Reducers->InvokeInsertResultEveryPrimitiveStructString(Context, Reducer); + return; + } + if (ReducerName == TEXT("insert_result_i32_string")) + { + FInsertResultI32StringArgs Args = ReducerEvent.Reducer.GetAsInsertResultI32String(); + UInsertResultI32StringReducer* Reducer = NewObject(); + Reducer->R = Args.R; + Reducers->InvokeInsertResultI32String(Context, Reducer); + return; + } + if (ReducerName == TEXT("insert_result_identity_string")) + { + FInsertResultIdentityStringArgs Args = ReducerEvent.Reducer.GetAsInsertResultIdentityString(); + UInsertResultIdentityStringReducer* Reducer = NewObject(); + Reducer->R = Args.R; + Reducers->InvokeInsertResultIdentityString(Context, Reducer); + return; + } + if (ReducerName == TEXT("insert_result_simple_enum_i32")) + { + FInsertResultSimpleEnumI32Args Args = ReducerEvent.Reducer.GetAsInsertResultSimpleEnumI32(); + UInsertResultSimpleEnumI32Reducer* Reducer = NewObject(); + Reducer->R = Args.R; + Reducers->InvokeInsertResultSimpleEnumI32(Context, Reducer); + return; + } + if (ReducerName == TEXT("insert_result_string_i32")) + { + FInsertResultStringI32Args Args = ReducerEvent.Reducer.GetAsInsertResultStringI32(); + UInsertResultStringI32Reducer* Reducer = NewObject(); + Reducer->R = Args.R; + Reducers->InvokeInsertResultStringI32(Context, Reducer); + return; + } + if (ReducerName == TEXT("insert_result_vec_i32_string")) + { + FInsertResultVecI32StringArgs Args = ReducerEvent.Reducer.GetAsInsertResultVecI32String(); + UInsertResultVecI32StringReducer* Reducer = NewObject(); + Reducer->R = Args.R; + Reducers->InvokeInsertResultVecI32String(Context, Reducer); + return; + } if (ReducerName == TEXT("insert_table_holds_table")) { FInsertTableHoldsTableArgs Args = ReducerEvent.Reducer.GetAsInsertTableHoldsTable(); diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Private/ModuleBindings/Tables/ResultEveryPrimitiveStructStringTable.g.cpp b/sdks/unreal/tests/TestClient/Source/TestClient/Private/ModuleBindings/Tables/ResultEveryPrimitiveStructStringTable.g.cpp new file mode 100644 index 00000000000..736e17ffa40 --- /dev/null +++ b/sdks/unreal/tests/TestClient/Source/TestClient/Private/ModuleBindings/Tables/ResultEveryPrimitiveStructStringTable.g.cpp @@ -0,0 +1,35 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#include "ModuleBindings/Tables/ResultEveryPrimitiveStructStringTable.g.h" +#include "DBCache/UniqueIndex.h" +#include "DBCache/BTreeUniqueIndex.h" +#include "DBCache/ClientCache.h" +#include "DBCache/TableCache.h" + +void UResultEveryPrimitiveStructStringTable::PostInitialize() +{ + /** Client cache init and setting up indexes*/ + Data = MakeShared>(); + + TSharedPtr> ResultEveryPrimitiveStructStringTable = Data->GetOrAdd(TableName); + + /***/ +} + +FTableAppliedDiff UResultEveryPrimitiveStructStringTable::Update(TArray> InsertsRef, TArray> DeletesRef) +{ + FTableAppliedDiff Diff = BaseUpdate(InsertsRef, DeletesRef, Data, TableName); + + return Diff; +} + +int32 UResultEveryPrimitiveStructStringTable::Count() const +{ + return GetRowCountFromTable(Data, TableName); +} + +TArray UResultEveryPrimitiveStructStringTable::Iter() const +{ + return GetAllRowsFromTable(Data, TableName); +} diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Private/ModuleBindings/Tables/ResultI32StringTable.g.cpp b/sdks/unreal/tests/TestClient/Source/TestClient/Private/ModuleBindings/Tables/ResultI32StringTable.g.cpp new file mode 100644 index 00000000000..feedde59d25 --- /dev/null +++ b/sdks/unreal/tests/TestClient/Source/TestClient/Private/ModuleBindings/Tables/ResultI32StringTable.g.cpp @@ -0,0 +1,35 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#include "ModuleBindings/Tables/ResultI32StringTable.g.h" +#include "DBCache/UniqueIndex.h" +#include "DBCache/BTreeUniqueIndex.h" +#include "DBCache/ClientCache.h" +#include "DBCache/TableCache.h" + +void UResultI32StringTable::PostInitialize() +{ + /** Client cache init and setting up indexes*/ + Data = MakeShared>(); + + TSharedPtr> ResultI32StringTable = Data->GetOrAdd(TableName); + + /***/ +} + +FTableAppliedDiff UResultI32StringTable::Update(TArray> InsertsRef, TArray> DeletesRef) +{ + FTableAppliedDiff Diff = BaseUpdate(InsertsRef, DeletesRef, Data, TableName); + + return Diff; +} + +int32 UResultI32StringTable::Count() const +{ + return GetRowCountFromTable(Data, TableName); +} + +TArray UResultI32StringTable::Iter() const +{ + return GetAllRowsFromTable(Data, TableName); +} diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Private/ModuleBindings/Tables/ResultIdentityStringTable.g.cpp b/sdks/unreal/tests/TestClient/Source/TestClient/Private/ModuleBindings/Tables/ResultIdentityStringTable.g.cpp new file mode 100644 index 00000000000..ea541f333f7 --- /dev/null +++ b/sdks/unreal/tests/TestClient/Source/TestClient/Private/ModuleBindings/Tables/ResultIdentityStringTable.g.cpp @@ -0,0 +1,35 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#include "ModuleBindings/Tables/ResultIdentityStringTable.g.h" +#include "DBCache/UniqueIndex.h" +#include "DBCache/BTreeUniqueIndex.h" +#include "DBCache/ClientCache.h" +#include "DBCache/TableCache.h" + +void UResultIdentityStringTable::PostInitialize() +{ + /** Client cache init and setting up indexes*/ + Data = MakeShared>(); + + TSharedPtr> ResultIdentityStringTable = Data->GetOrAdd(TableName); + + /***/ +} + +FTableAppliedDiff UResultIdentityStringTable::Update(TArray> InsertsRef, TArray> DeletesRef) +{ + FTableAppliedDiff Diff = BaseUpdate(InsertsRef, DeletesRef, Data, TableName); + + return Diff; +} + +int32 UResultIdentityStringTable::Count() const +{ + return GetRowCountFromTable(Data, TableName); +} + +TArray UResultIdentityStringTable::Iter() const +{ + return GetAllRowsFromTable(Data, TableName); +} diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Private/ModuleBindings/Tables/ResultSimpleEnumI32Table.g.cpp b/sdks/unreal/tests/TestClient/Source/TestClient/Private/ModuleBindings/Tables/ResultSimpleEnumI32Table.g.cpp new file mode 100644 index 00000000000..230ce4f65c6 --- /dev/null +++ b/sdks/unreal/tests/TestClient/Source/TestClient/Private/ModuleBindings/Tables/ResultSimpleEnumI32Table.g.cpp @@ -0,0 +1,35 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#include "ModuleBindings/Tables/ResultSimpleEnumI32Table.g.h" +#include "DBCache/UniqueIndex.h" +#include "DBCache/BTreeUniqueIndex.h" +#include "DBCache/ClientCache.h" +#include "DBCache/TableCache.h" + +void UResultSimpleEnumI32Table::PostInitialize() +{ + /** Client cache init and setting up indexes*/ + Data = MakeShared>(); + + TSharedPtr> ResultSimpleEnumI32Table = Data->GetOrAdd(TableName); + + /***/ +} + +FTableAppliedDiff UResultSimpleEnumI32Table::Update(TArray> InsertsRef, TArray> DeletesRef) +{ + FTableAppliedDiff Diff = BaseUpdate(InsertsRef, DeletesRef, Data, TableName); + + return Diff; +} + +int32 UResultSimpleEnumI32Table::Count() const +{ + return GetRowCountFromTable(Data, TableName); +} + +TArray UResultSimpleEnumI32Table::Iter() const +{ + return GetAllRowsFromTable(Data, TableName); +} diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Private/ModuleBindings/Tables/ResultStringI32Table.g.cpp b/sdks/unreal/tests/TestClient/Source/TestClient/Private/ModuleBindings/Tables/ResultStringI32Table.g.cpp new file mode 100644 index 00000000000..a0c29a63b61 --- /dev/null +++ b/sdks/unreal/tests/TestClient/Source/TestClient/Private/ModuleBindings/Tables/ResultStringI32Table.g.cpp @@ -0,0 +1,35 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#include "ModuleBindings/Tables/ResultStringI32Table.g.h" +#include "DBCache/UniqueIndex.h" +#include "DBCache/BTreeUniqueIndex.h" +#include "DBCache/ClientCache.h" +#include "DBCache/TableCache.h" + +void UResultStringI32Table::PostInitialize() +{ + /** Client cache init and setting up indexes*/ + Data = MakeShared>(); + + TSharedPtr> ResultStringI32Table = Data->GetOrAdd(TableName); + + /***/ +} + +FTableAppliedDiff UResultStringI32Table::Update(TArray> InsertsRef, TArray> DeletesRef) +{ + FTableAppliedDiff Diff = BaseUpdate(InsertsRef, DeletesRef, Data, TableName); + + return Diff; +} + +int32 UResultStringI32Table::Count() const +{ + return GetRowCountFromTable(Data, TableName); +} + +TArray UResultStringI32Table::Iter() const +{ + return GetAllRowsFromTable(Data, TableName); +} diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Private/ModuleBindings/Tables/ResultVecI32StringTable.g.cpp b/sdks/unreal/tests/TestClient/Source/TestClient/Private/ModuleBindings/Tables/ResultVecI32StringTable.g.cpp new file mode 100644 index 00000000000..7a7c09add46 --- /dev/null +++ b/sdks/unreal/tests/TestClient/Source/TestClient/Private/ModuleBindings/Tables/ResultVecI32StringTable.g.cpp @@ -0,0 +1,35 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#include "ModuleBindings/Tables/ResultVecI32StringTable.g.h" +#include "DBCache/UniqueIndex.h" +#include "DBCache/BTreeUniqueIndex.h" +#include "DBCache/ClientCache.h" +#include "DBCache/TableCache.h" + +void UResultVecI32StringTable::PostInitialize() +{ + /** Client cache init and setting up indexes*/ + Data = MakeShared>(); + + TSharedPtr> ResultVecI32StringTable = Data->GetOrAdd(TableName); + + /***/ +} + +FTableAppliedDiff UResultVecI32StringTable::Update(TArray> InsertsRef, TArray> DeletesRef) +{ + FTableAppliedDiff Diff = BaseUpdate(InsertsRef, DeletesRef, Data, TableName); + + return Diff; +} + +int32 UResultVecI32StringTable::Count() const +{ + return GetRowCountFromTable(Data, TableName); +} + +TArray UResultVecI32StringTable::Iter() const +{ + return GetAllRowsFromTable(Data, TableName); +} diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Private/Tests/SpacetimeFullClientTests.cpp b/sdks/unreal/tests/TestClient/Source/TestClient/Private/Tests/SpacetimeFullClientTests.cpp index 6f4dfd86feb..a813f6b2db5 100644 --- a/sdks/unreal/tests/TestClient/Source/TestClient/Private/Tests/SpacetimeFullClientTests.cpp +++ b/sdks/unreal/tests/TestClient/Source/TestClient/Private/Tests/SpacetimeFullClientTests.cpp @@ -16,6 +16,12 @@ #include "Tests/PrimitiveHandlerList.def" #include "Connection/Credentials.h" +#include "ModuleBindings/Tables/ResultEveryPrimitiveStructStringTable.g.h" +#include "ModuleBindings/Tables/ResultI32StringTable.g.h" +#include "ModuleBindings/Tables/ResultIdentityStringTable.g.h" +#include "ModuleBindings/Tables/ResultSimpleEnumI32Table.g.h" +#include "ModuleBindings/Tables/ResultStringI32Table.g.h" +#include "ModuleBindings/Tables/ResultVecI32StringTable.g.h" // #include "HAL/IPlatformFile.h" @@ -1077,6 +1083,108 @@ bool FInsertOptionNoneTest::RunTest(const FString &Parameters) return true; } +bool FInsertResultOkTest::RunTest(const FString &Parameters) +{ + TestName = "InsertResultOk"; + + if (!ValidateParameterConfig(this)) + { + return false; + } + + // Create and register a test counter to track completion. + UResultActionsHandler *Handler = CreateTestHandler(); + Handler->Counter->Register(TEXT("InsertResultI32String")); + Handler->Counter->Register(TEXT("InsertResultStringI32")); + Handler->Counter->Register(TEXT("InsertResultIdentityString")); + Handler->Counter->Register(TEXT("InsertResultSimpleEnumI32")); + Handler->Counter->Register(TEXT("InsertResultEveryPrimitiveStructString")); + Handler->Counter->Register(TEXT("InsertResultVecI32String")); + + UDbConnection *Connection = ConnectThen(Handler->Counter, TestName, [this, Handler](UDbConnection *Conn) + { + // Subscribe to the insert event for each table. + Conn->Db->ResultI32String->OnInsert.AddDynamic(Handler, &UResultActionsHandler::OnInsertResultI32String); + Conn->Db->ResultStringI32->OnInsert.AddDynamic(Handler, &UResultActionsHandler::OnInsertResultStringI32); + Conn->Db->ResultIdentityString->OnInsert.AddDynamic(Handler, &UResultActionsHandler::OnInsertResultIdentityString); + Conn->Db->ResultSimpleEnumI32->OnInsert.AddDynamic(Handler, &UResultActionsHandler::OnInsertResultSimpleEnumI32); + Conn->Db->ResultEveryPrimitiveStructString->OnInsert.AddDynamic(Handler, &UResultActionsHandler::OnInsertResultEveryPrimitiveStructString); + Conn->Db->ResultVecI32String->OnInsert.AddDynamic(Handler, &UResultActionsHandler::OnInsertResultVecI32String); + + SubscribeAllThen(Conn, [this, Handler, Conn](FSubscriptionEventContext Ctx) + { + if (!AssertAllTablesEmpty(this, Conn->Db)) + { + Handler->Counter->Abort(); + return; + } + + // Set expected Ok values + Handler->ExpectedResultI32StringType = FTestClientResultInt32String::Ok(42); + Handler->ExpectedResultStringI32Type = FTestClientResultStringInt32::Ok(TEXT("Testing String")); + + FSpacetimeDBIdentity Identity; + Ctx.TryGetIdentity(Identity); + Handler->ExpectedResultIdentityStringType = FTestClientResultIdentityString::Ok(Identity); + + Handler->ExpectedResultSimpleEnumI32Type = FTestClientResultSimpleEnumInt32::Ok(ESimpleEnumType::One); + FSpacetimeDBUInt128 UInt128 = { 0, 4 }; + FSpacetimeDBUInt256 UInt256 = { FSpacetimeDBUInt128(0, 0), FSpacetimeDBUInt128(0, 5) }; + + FSpacetimeDBInt128 Int128 = { 0, static_cast(-5) }; + FSpacetimeDBInt256 Int256 = { FSpacetimeDBUInt128(0, 0), FSpacetimeDBUInt128(0, static_cast(-5)) }; + + FSpacetimeDBUInt128 UInt128p = { 0x0102030405060708, 0x090a0b0c0d0e0f10 }; + FSpacetimeDBUInt256 UInt256p = { FSpacetimeDBUInt128(0x0102030405060708, 0x090a0b0c0d0e0f10), FSpacetimeDBUInt128(0x1112131415161718, 0x191a1b1c1d1e1f20)}; + + FSpacetimeDBInt128 Int128p = { static_cast(-0x0102030405060708), static_cast(-0x090a0b0c0d0e0f10)}; + FSpacetimeDBInt256 Int256p = { FSpacetimeDBUInt128(static_cast(-0x0102030405060708), static_cast(-0x090a0b0c0d0e0f10)), + FSpacetimeDBUInt128(static_cast(-0x1112131415161718), static_cast(-0x191a1b1c1d1e1f20)) }; + + FEveryPrimitiveStructType EveryPrimitiveStructType; + EveryPrimitiveStructType.A = { 0x01 }; + EveryPrimitiveStructType.B = { 0x0102 }; + EveryPrimitiveStructType.C = { 0x01020304 }; + EveryPrimitiveStructType.D = { 0x0102030405060708 }; + EveryPrimitiveStructType.E = { UInt128p }; + EveryPrimitiveStructType.F = { UInt256p }; + EveryPrimitiveStructType.G = { -0x01 }; + EveryPrimitiveStructType.H = { -0x0102 }; + EveryPrimitiveStructType.I = { -0x01020304 }; + EveryPrimitiveStructType.J = { -0x0102030405060708 }; + EveryPrimitiveStructType.K = { Int128p }; + EveryPrimitiveStructType.L = { Int256p }; + EveryPrimitiveStructType.M = { false }; + EveryPrimitiveStructType.N = { 1.0 }; + EveryPrimitiveStructType.O = { -1.0 }; + EveryPrimitiveStructType.P = { "string" }; + EveryPrimitiveStructType.Q = { FSpacetimeDBIdentity() }; + EveryPrimitiveStructType.R = { FSpacetimeDBConnectionId() }; + EveryPrimitiveStructType.S = { FSpacetimeDBTimestamp(9876543210) }; + EveryPrimitiveStructType.T = { FSpacetimeDBTimeDuration(-67419000000003LL) }; + Handler->ExpectedResultEveryPrimitiveStructStringType = FTestClientResultEveryPrimitiveStructString::Ok(EveryPrimitiveStructType); + + TArray Vec; + Vec.Add(3); + Vec.Add(2); + Vec.Add(1); + Vec.Add(0); + Handler->ExpectedResultVecI32StringType = FTestClientResultVecInt32String::Ok(Vec); + // Call the reducers with Ok values + Ctx.Reducers->InsertResultI32String(Handler->ExpectedResultI32StringType); + Ctx.Reducers->InsertResultStringI32(Handler->ExpectedResultStringI32Type); + Ctx.Reducers->InsertResultIdentityString(Handler->ExpectedResultIdentityStringType); + Ctx.Reducers->InsertResultSimpleEnumI32(Handler->ExpectedResultSimpleEnumI32Type); + Ctx.Reducers->InsertResultEveryPrimitiveStructString(Handler->ExpectedResultEveryPrimitiveStructStringType); + Ctx.Reducers->InsertResultVecI32String(Handler->ExpectedResultVecI32StringType); + }); + }); + + ADD_LATENT_AUTOMATION_COMMAND(FWaitForTestCounter(*this, TestName, Handler->Counter, FPlatformTime::Seconds())); + + return true; +} + bool FInsertStructTest::RunTest(const FString &Parameters) { TestName = "InsertStruct"; diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Private/Tests/TestHandler.cpp b/sdks/unreal/tests/TestClient/Source/TestClient/Private/Tests/TestHandler.cpp index 852f67b3244..7c7fa04462d 100644 --- a/sdks/unreal/tests/TestClient/Source/TestClient/Private/Tests/TestHandler.cpp +++ b/sdks/unreal/tests/TestClient/Source/TestClient/Private/Tests/TestHandler.cpp @@ -1109,6 +1109,78 @@ void UOptionActionsHandler::OnInsertOptionVecOptionI32(const FEventContext& Cont } } +void UResultActionsHandler::OnInsertResultI32String(const FEventContext& Context, const FResultI32StringType& Value) +{ + static const FString Name(TEXT("InsertResultI32String")); + if (ExpectedResultI32StringType == Value.R) + { + Counter->MarkSuccess(Name); + } + else { + Counter->MarkFailure(Name, TEXT("Unexpected value")); + } +} + +void UResultActionsHandler::OnInsertResultStringI32(const FEventContext& Context, const FResultStringI32Type& Value) +{ + static const FString Name(TEXT("InsertResultStringI32")); + if (ExpectedResultStringI32Type == Value.R) + { + Counter->MarkSuccess(Name); + } + else { + Counter->MarkFailure(Name, TEXT("Unexpected value")); + } +} + +void UResultActionsHandler::OnInsertResultIdentityString(const FEventContext& Context, const FResultIdentityStringType& Value) +{ + static const FString Name(TEXT("InsertResultIdentityString")); + if (ExpectedResultIdentityStringType == Value.R) + { + Counter->MarkSuccess(Name); + } + else { + Counter->MarkFailure(Name, TEXT("Unexpected value")); + } +} + +void UResultActionsHandler::OnInsertResultSimpleEnumI32(const FEventContext& Context, const FResultSimpleEnumI32Type& Value) +{ + static const FString Name(TEXT("InsertResultSimpleEnumI32")); + if (ExpectedResultSimpleEnumI32Type == Value.R) + { + Counter->MarkSuccess(Name); + } + else { + Counter->MarkFailure(Name, TEXT("Unexpected value")); + } +} + +void UResultActionsHandler::OnInsertResultEveryPrimitiveStructString(const FEventContext& Context, const FResultEveryPrimitiveStructStringType& Value) +{ + static const FString Name(TEXT("InsertResultEveryPrimitiveStructString")); + if (ExpectedResultEveryPrimitiveStructStringType == Value.R) + { + Counter->MarkSuccess(Name); + } + else { + Counter->MarkFailure(Name, TEXT("Unexpected value")); + } +} + +void UResultActionsHandler::OnInsertResultVecI32String(const FEventContext& Context, const FResultVecI32StringType& Value) +{ + static const FString Name(TEXT("InsertResultVecI32String")); + if (ExpectedResultVecI32StringType == Value.R) + { + Counter->MarkSuccess(Name); + } + else { + Counter->MarkFailure(Name, TEXT("Unexpected value")); + } +} + void UStructActionsHandler::OnInsertOneUnitStruct(const FEventContext& Context, const FOneUnitStructType& Value) { static const FString Name(TEXT("InsertOneUnitStruct")); diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Reducers/InsertResultEveryPrimitiveStructString.g.h b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Reducers/InsertResultEveryPrimitiveStructString.g.h new file mode 100644 index 00000000000..837756ebbfb --- /dev/null +++ b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Reducers/InsertResultEveryPrimitiveStructString.g.h @@ -0,0 +1,55 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#pragma once +#include "CoreMinimal.h" +#include "BSATN/UESpacetimeDB.h" +#include "ModuleBindings/ReducerBase.g.h" +#include "ModuleBindings/Results/TestClientResultEveryPrimitiveStructString.g.h" +#include "ModuleBindings/Types/EveryPrimitiveStructType.g.h" +#include "InsertResultEveryPrimitiveStructString.g.generated.h" + +// Reducer arguments struct for InsertResultEveryPrimitiveStructString +USTRUCT(BlueprintType) +struct TESTCLIENT_API FInsertResultEveryPrimitiveStructStringArgs +{ + GENERATED_BODY() + + UPROPERTY(BlueprintReadWrite, Category="SpacetimeDB") + FTestClientResultEveryPrimitiveStructString R; + + FInsertResultEveryPrimitiveStructStringArgs() = default; + + FInsertResultEveryPrimitiveStructStringArgs(const FTestClientResultEveryPrimitiveStructString& InR) + : R(InR) + {} + + + FORCEINLINE bool operator==(const FInsertResultEveryPrimitiveStructStringArgs& Other) const + { + return R == Other.R; + } + FORCEINLINE bool operator!=(const FInsertResultEveryPrimitiveStructStringArgs& Other) const + { + return !(*this == Other); + } +}; + +namespace UE::SpacetimeDB +{ + UE_SPACETIMEDB_STRUCT(FInsertResultEveryPrimitiveStructStringArgs, R); +} + +// Reducer class for internal dispatching +UCLASS(BlueprintType) +class TESTCLIENT_API UInsertResultEveryPrimitiveStructStringReducer : public UReducerBase +{ + GENERATED_BODY() + +public: + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + FTestClientResultEveryPrimitiveStructString R; + +}; + + diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Reducers/InsertResultI32String.g.h b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Reducers/InsertResultI32String.g.h new file mode 100644 index 00000000000..8ea621b12dc --- /dev/null +++ b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Reducers/InsertResultI32String.g.h @@ -0,0 +1,54 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#pragma once +#include "CoreMinimal.h" +#include "BSATN/UESpacetimeDB.h" +#include "ModuleBindings/ReducerBase.g.h" +#include "ModuleBindings/Results/TestClientResultInt32String.g.h" +#include "InsertResultI32String.g.generated.h" + +// Reducer arguments struct for InsertResultI32String +USTRUCT(BlueprintType) +struct TESTCLIENT_API FInsertResultI32StringArgs +{ + GENERATED_BODY() + + UPROPERTY(BlueprintReadWrite, Category="SpacetimeDB") + FTestClientResultInt32String R; + + FInsertResultI32StringArgs() = default; + + FInsertResultI32StringArgs(const FTestClientResultInt32String& InR) + : R(InR) + {} + + + FORCEINLINE bool operator==(const FInsertResultI32StringArgs& Other) const + { + return R == Other.R; + } + FORCEINLINE bool operator!=(const FInsertResultI32StringArgs& Other) const + { + return !(*this == Other); + } +}; + +namespace UE::SpacetimeDB +{ + UE_SPACETIMEDB_STRUCT(FInsertResultI32StringArgs, R); +} + +// Reducer class for internal dispatching +UCLASS(BlueprintType) +class TESTCLIENT_API UInsertResultI32StringReducer : public UReducerBase +{ + GENERATED_BODY() + +public: + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + FTestClientResultInt32String R; + +}; + + diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Reducers/InsertResultIdentityString.g.h b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Reducers/InsertResultIdentityString.g.h new file mode 100644 index 00000000000..d2f811c780b --- /dev/null +++ b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Reducers/InsertResultIdentityString.g.h @@ -0,0 +1,55 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#pragma once +#include "CoreMinimal.h" +#include "BSATN/UESpacetimeDB.h" +#include "ModuleBindings/ReducerBase.g.h" +#include "ModuleBindings/Results/TestClientResultIdentityString.g.h" +#include "Types/Builtins.h" +#include "InsertResultIdentityString.g.generated.h" + +// Reducer arguments struct for InsertResultIdentityString +USTRUCT(BlueprintType) +struct TESTCLIENT_API FInsertResultIdentityStringArgs +{ + GENERATED_BODY() + + UPROPERTY(BlueprintReadWrite, Category="SpacetimeDB") + FTestClientResultIdentityString R; + + FInsertResultIdentityStringArgs() = default; + + FInsertResultIdentityStringArgs(const FTestClientResultIdentityString& InR) + : R(InR) + {} + + + FORCEINLINE bool operator==(const FInsertResultIdentityStringArgs& Other) const + { + return R == Other.R; + } + FORCEINLINE bool operator!=(const FInsertResultIdentityStringArgs& Other) const + { + return !(*this == Other); + } +}; + +namespace UE::SpacetimeDB +{ + UE_SPACETIMEDB_STRUCT(FInsertResultIdentityStringArgs, R); +} + +// Reducer class for internal dispatching +UCLASS(BlueprintType) +class TESTCLIENT_API UInsertResultIdentityStringReducer : public UReducerBase +{ + GENERATED_BODY() + +public: + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + FTestClientResultIdentityString R; + +}; + + diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Reducers/InsertResultSimpleEnumI32.g.h b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Reducers/InsertResultSimpleEnumI32.g.h new file mode 100644 index 00000000000..e51dfccab9d --- /dev/null +++ b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Reducers/InsertResultSimpleEnumI32.g.h @@ -0,0 +1,55 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#pragma once +#include "CoreMinimal.h" +#include "BSATN/UESpacetimeDB.h" +#include "ModuleBindings/ReducerBase.g.h" +#include "ModuleBindings/Results/TestClientResultSimpleEnumInt32.g.h" +#include "ModuleBindings/Types/SimpleEnumType.g.h" +#include "InsertResultSimpleEnumI32.g.generated.h" + +// Reducer arguments struct for InsertResultSimpleEnumI32 +USTRUCT(BlueprintType) +struct TESTCLIENT_API FInsertResultSimpleEnumI32Args +{ + GENERATED_BODY() + + UPROPERTY(BlueprintReadWrite, Category="SpacetimeDB") + FTestClientResultSimpleEnumInt32 R; + + FInsertResultSimpleEnumI32Args() = default; + + FInsertResultSimpleEnumI32Args(const FTestClientResultSimpleEnumInt32& InR) + : R(InR) + {} + + + FORCEINLINE bool operator==(const FInsertResultSimpleEnumI32Args& Other) const + { + return R == Other.R; + } + FORCEINLINE bool operator!=(const FInsertResultSimpleEnumI32Args& Other) const + { + return !(*this == Other); + } +}; + +namespace UE::SpacetimeDB +{ + UE_SPACETIMEDB_STRUCT(FInsertResultSimpleEnumI32Args, R); +} + +// Reducer class for internal dispatching +UCLASS(BlueprintType) +class TESTCLIENT_API UInsertResultSimpleEnumI32Reducer : public UReducerBase +{ + GENERATED_BODY() + +public: + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + FTestClientResultSimpleEnumInt32 R; + +}; + + diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Reducers/InsertResultStringI32.g.h b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Reducers/InsertResultStringI32.g.h new file mode 100644 index 00000000000..6e1b9867c14 --- /dev/null +++ b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Reducers/InsertResultStringI32.g.h @@ -0,0 +1,54 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#pragma once +#include "CoreMinimal.h" +#include "BSATN/UESpacetimeDB.h" +#include "ModuleBindings/ReducerBase.g.h" +#include "ModuleBindings/Results/TestClientResultStringInt32.g.h" +#include "InsertResultStringI32.g.generated.h" + +// Reducer arguments struct for InsertResultStringI32 +USTRUCT(BlueprintType) +struct TESTCLIENT_API FInsertResultStringI32Args +{ + GENERATED_BODY() + + UPROPERTY(BlueprintReadWrite, Category="SpacetimeDB") + FTestClientResultStringInt32 R; + + FInsertResultStringI32Args() = default; + + FInsertResultStringI32Args(const FTestClientResultStringInt32& InR) + : R(InR) + {} + + + FORCEINLINE bool operator==(const FInsertResultStringI32Args& Other) const + { + return R == Other.R; + } + FORCEINLINE bool operator!=(const FInsertResultStringI32Args& Other) const + { + return !(*this == Other); + } +}; + +namespace UE::SpacetimeDB +{ + UE_SPACETIMEDB_STRUCT(FInsertResultStringI32Args, R); +} + +// Reducer class for internal dispatching +UCLASS(BlueprintType) +class TESTCLIENT_API UInsertResultStringI32Reducer : public UReducerBase +{ + GENERATED_BODY() + +public: + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + FTestClientResultStringInt32 R; + +}; + + diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Reducers/InsertResultVecI32String.g.h b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Reducers/InsertResultVecI32String.g.h new file mode 100644 index 00000000000..4c3fe5e92da --- /dev/null +++ b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Reducers/InsertResultVecI32String.g.h @@ -0,0 +1,54 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#pragma once +#include "CoreMinimal.h" +#include "BSATN/UESpacetimeDB.h" +#include "ModuleBindings/ReducerBase.g.h" +#include "ModuleBindings/Results/TestClientResultVecInt32String.g.h" +#include "InsertResultVecI32String.g.generated.h" + +// Reducer arguments struct for InsertResultVecI32String +USTRUCT(BlueprintType) +struct TESTCLIENT_API FInsertResultVecI32StringArgs +{ + GENERATED_BODY() + + UPROPERTY(BlueprintReadWrite, Category="SpacetimeDB") + FTestClientResultVecInt32String R; + + FInsertResultVecI32StringArgs() = default; + + FInsertResultVecI32StringArgs(const FTestClientResultVecInt32String& InR) + : R(InR) + {} + + + FORCEINLINE bool operator==(const FInsertResultVecI32StringArgs& Other) const + { + return R == Other.R; + } + FORCEINLINE bool operator!=(const FInsertResultVecI32StringArgs& Other) const + { + return !(*this == Other); + } +}; + +namespace UE::SpacetimeDB +{ + UE_SPACETIMEDB_STRUCT(FInsertResultVecI32StringArgs, R); +} + +// Reducer class for internal dispatching +UCLASS(BlueprintType) +class TESTCLIENT_API UInsertResultVecI32StringReducer : public UReducerBase +{ + GENERATED_BODY() + +public: + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + FTestClientResultVecInt32String R; + +}; + + diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Results/TestClientResultEveryPrimitiveStructString.g.h b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Results/TestClientResultEveryPrimitiveStructString.g.h new file mode 100644 index 00000000000..b70751e72ea --- /dev/null +++ b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Results/TestClientResultEveryPrimitiveStructString.g.h @@ -0,0 +1,101 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#pragma once +#include "CoreMinimal.h" +#include "BSATN/UESpacetimeDB.h" +#include "ModuleBindings/Types/EveryPrimitiveStructType.g.h" +#include "TestClientResultEveryPrimitiveStructString.g.generated.h" + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FTestClientResultEveryPrimitiveStructString +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SpacetimeDB") + bool bIsOk = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SpacetimeDB", meta = (EditCondition = "bIsOk")) + FEveryPrimitiveStructType OkValue; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SpacetimeDB", meta = (EditCondition = "!bIsOk")) + FString ErrValue; + + FTestClientResultEveryPrimitiveStructString() = default; + + static FTestClientResultEveryPrimitiveStructString Ok(const FEveryPrimitiveStructType& InValue) + { + FTestClientResultEveryPrimitiveStructString Result; + Result.bIsOk = true; + Result.OkValue = InValue; + return Result; + } + + static FTestClientResultEveryPrimitiveStructString Err(const FString& InValue) + { + FTestClientResultEveryPrimitiveStructString Result; + Result.bIsOk = false; + Result.ErrValue = InValue; + return Result; + } + + bool IsOk() const { return bIsOk; } + bool IsErr() const { return !bIsOk; } + + const FEveryPrimitiveStructType& GetOk() const + { + check(bIsOk); + return OkValue; + } + + const FString& GetErr() const + { + check(!bIsOk); + return ErrValue; + } + + FORCEINLINE bool operator==(const FTestClientResultEveryPrimitiveStructString& Other) const + { + if (bIsOk != Other.bIsOk) return false; + if (bIsOk) + { + return OkValue == Other.OkValue; + } + else + { + return ErrValue == Other.ErrValue; + } + } + + FORCEINLINE bool operator!=(const FTestClientResultEveryPrimitiveStructString& Other) const + { + return !(*this == Other); + } +}; + +/** + * Custom hash function for FTestClientResultEveryPrimitiveStructString. + * Hashes the bIsOk flag and the appropriate value. + * @param Result The FTestClientResultEveryPrimitiveStructString instance to hash. + * @return The combined hash value. + */ +FORCEINLINE uint32 GetTypeHash(const FTestClientResultEveryPrimitiveStructString& Result) +{ + uint32 Hash = GetTypeHash(Result.bIsOk); + if (Result.bIsOk) + { + Hash = HashCombine(Hash, GetTypeHash(Result.OkValue)); + } + else + { + Hash = HashCombine(Hash, GetTypeHash(Result.ErrValue)); + } + return Hash; +} + +namespace UE::SpacetimeDB +{ + UE_SPACETIMEDB_ENABLE_TARRAY(FTestClientResultEveryPrimitiveStructString); + + UE_SPACETIMEDB_RESULT(FTestClientResultEveryPrimitiveStructString, bIsOk, OkValue, ErrValue); +} diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Results/TestClientResultIdentityString.g.h b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Results/TestClientResultIdentityString.g.h new file mode 100644 index 00000000000..d4fef91a60d --- /dev/null +++ b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Results/TestClientResultIdentityString.g.h @@ -0,0 +1,101 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#pragma once +#include "CoreMinimal.h" +#include "BSATN/UESpacetimeDB.h" +#include "Types/Builtins.h" +#include "TestClientResultIdentityString.g.generated.h" + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FTestClientResultIdentityString +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SpacetimeDB") + bool bIsOk = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SpacetimeDB", meta = (EditCondition = "bIsOk")) + FSpacetimeDBIdentity OkValue; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SpacetimeDB", meta = (EditCondition = "!bIsOk")) + FString ErrValue; + + FTestClientResultIdentityString() = default; + + static FTestClientResultIdentityString Ok(const FSpacetimeDBIdentity& InValue) + { + FTestClientResultIdentityString Result; + Result.bIsOk = true; + Result.OkValue = InValue; + return Result; + } + + static FTestClientResultIdentityString Err(const FString& InValue) + { + FTestClientResultIdentityString Result; + Result.bIsOk = false; + Result.ErrValue = InValue; + return Result; + } + + bool IsOk() const { return bIsOk; } + bool IsErr() const { return !bIsOk; } + + const FSpacetimeDBIdentity& GetOk() const + { + check(bIsOk); + return OkValue; + } + + const FString& GetErr() const + { + check(!bIsOk); + return ErrValue; + } + + FORCEINLINE bool operator==(const FTestClientResultIdentityString& Other) const + { + if (bIsOk != Other.bIsOk) return false; + if (bIsOk) + { + return OkValue == Other.OkValue; + } + else + { + return ErrValue == Other.ErrValue; + } + } + + FORCEINLINE bool operator!=(const FTestClientResultIdentityString& Other) const + { + return !(*this == Other); + } +}; + +/** + * Custom hash function for FTestClientResultIdentityString. + * Hashes the bIsOk flag and the appropriate value. + * @param Result The FTestClientResultIdentityString instance to hash. + * @return The combined hash value. + */ +FORCEINLINE uint32 GetTypeHash(const FTestClientResultIdentityString& Result) +{ + uint32 Hash = GetTypeHash(Result.bIsOk); + if (Result.bIsOk) + { + Hash = HashCombine(Hash, GetTypeHash(Result.OkValue)); + } + else + { + Hash = HashCombine(Hash, GetTypeHash(Result.ErrValue)); + } + return Hash; +} + +namespace UE::SpacetimeDB +{ + UE_SPACETIMEDB_ENABLE_TARRAY(FTestClientResultIdentityString); + + UE_SPACETIMEDB_RESULT(FTestClientResultIdentityString, bIsOk, OkValue, ErrValue); +} diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Results/TestClientResultInt32String.g.h b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Results/TestClientResultInt32String.g.h new file mode 100644 index 00000000000..b8fc02c91e8 --- /dev/null +++ b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Results/TestClientResultInt32String.g.h @@ -0,0 +1,100 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#pragma once +#include "CoreMinimal.h" +#include "BSATN/UESpacetimeDB.h" +#include "TestClientResultInt32String.g.generated.h" + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FTestClientResultInt32String +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SpacetimeDB") + bool bIsOk = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SpacetimeDB", meta = (EditCondition = "bIsOk")) + int32 OkValue; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SpacetimeDB", meta = (EditCondition = "!bIsOk")) + FString ErrValue; + + FTestClientResultInt32String() = default; + + static FTestClientResultInt32String Ok(const int32& InValue) + { + FTestClientResultInt32String Result; + Result.bIsOk = true; + Result.OkValue = InValue; + return Result; + } + + static FTestClientResultInt32String Err(const FString& InValue) + { + FTestClientResultInt32String Result; + Result.bIsOk = false; + Result.ErrValue = InValue; + return Result; + } + + bool IsOk() const { return bIsOk; } + bool IsErr() const { return !bIsOk; } + + const int32& GetOk() const + { + check(bIsOk); + return OkValue; + } + + const FString& GetErr() const + { + check(!bIsOk); + return ErrValue; + } + + FORCEINLINE bool operator==(const FTestClientResultInt32String& Other) const + { + if (bIsOk != Other.bIsOk) return false; + if (bIsOk) + { + return OkValue == Other.OkValue; + } + else + { + return ErrValue == Other.ErrValue; + } + } + + FORCEINLINE bool operator!=(const FTestClientResultInt32String& Other) const + { + return !(*this == Other); + } +}; + +/** + * Custom hash function for FTestClientResultInt32String. + * Hashes the bIsOk flag and the appropriate value. + * @param Result The FTestClientResultInt32String instance to hash. + * @return The combined hash value. + */ +FORCEINLINE uint32 GetTypeHash(const FTestClientResultInt32String& Result) +{ + uint32 Hash = GetTypeHash(Result.bIsOk); + if (Result.bIsOk) + { + Hash = HashCombine(Hash, GetTypeHash(Result.OkValue)); + } + else + { + Hash = HashCombine(Hash, GetTypeHash(Result.ErrValue)); + } + return Hash; +} + +namespace UE::SpacetimeDB +{ + UE_SPACETIMEDB_ENABLE_TARRAY(FTestClientResultInt32String); + + UE_SPACETIMEDB_RESULT(FTestClientResultInt32String, bIsOk, OkValue, ErrValue); +} diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Results/TestClientResultSimpleEnumInt32.g.h b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Results/TestClientResultSimpleEnumInt32.g.h new file mode 100644 index 00000000000..1f3a9fff848 --- /dev/null +++ b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Results/TestClientResultSimpleEnumInt32.g.h @@ -0,0 +1,101 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#pragma once +#include "CoreMinimal.h" +#include "BSATN/UESpacetimeDB.h" +#include "ModuleBindings/Types/SimpleEnumType.g.h" +#include "TestClientResultSimpleEnumInt32.g.generated.h" + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FTestClientResultSimpleEnumInt32 +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SpacetimeDB") + bool bIsOk = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SpacetimeDB", meta = (EditCondition = "bIsOk")) + ESimpleEnumType OkValue; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SpacetimeDB", meta = (EditCondition = "!bIsOk")) + int32 ErrValue; + + FTestClientResultSimpleEnumInt32() = default; + + static FTestClientResultSimpleEnumInt32 Ok(const ESimpleEnumType& InValue) + { + FTestClientResultSimpleEnumInt32 Result; + Result.bIsOk = true; + Result.OkValue = InValue; + return Result; + } + + static FTestClientResultSimpleEnumInt32 Err(const int32& InValue) + { + FTestClientResultSimpleEnumInt32 Result; + Result.bIsOk = false; + Result.ErrValue = InValue; + return Result; + } + + bool IsOk() const { return bIsOk; } + bool IsErr() const { return !bIsOk; } + + const ESimpleEnumType& GetOk() const + { + check(bIsOk); + return OkValue; + } + + const int32& GetErr() const + { + check(!bIsOk); + return ErrValue; + } + + FORCEINLINE bool operator==(const FTestClientResultSimpleEnumInt32& Other) const + { + if (bIsOk != Other.bIsOk) return false; + if (bIsOk) + { + return OkValue == Other.OkValue; + } + else + { + return ErrValue == Other.ErrValue; + } + } + + FORCEINLINE bool operator!=(const FTestClientResultSimpleEnumInt32& Other) const + { + return !(*this == Other); + } +}; + +/** + * Custom hash function for FTestClientResultSimpleEnumInt32. + * Hashes the bIsOk flag and the appropriate value. + * @param Result The FTestClientResultSimpleEnumInt32 instance to hash. + * @return The combined hash value. + */ +FORCEINLINE uint32 GetTypeHash(const FTestClientResultSimpleEnumInt32& Result) +{ + uint32 Hash = GetTypeHash(Result.bIsOk); + if (Result.bIsOk) + { + Hash = HashCombine(Hash, GetTypeHash(Result.OkValue)); + } + else + { + Hash = HashCombine(Hash, GetTypeHash(Result.ErrValue)); + } + return Hash; +} + +namespace UE::SpacetimeDB +{ + UE_SPACETIMEDB_ENABLE_TARRAY(FTestClientResultSimpleEnumInt32); + + UE_SPACETIMEDB_RESULT(FTestClientResultSimpleEnumInt32, bIsOk, OkValue, ErrValue); +} diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Results/TestClientResultStringInt32.g.h b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Results/TestClientResultStringInt32.g.h new file mode 100644 index 00000000000..b1df79a3245 --- /dev/null +++ b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Results/TestClientResultStringInt32.g.h @@ -0,0 +1,100 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#pragma once +#include "CoreMinimal.h" +#include "BSATN/UESpacetimeDB.h" +#include "TestClientResultStringInt32.g.generated.h" + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FTestClientResultStringInt32 +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SpacetimeDB") + bool bIsOk = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SpacetimeDB", meta = (EditCondition = "bIsOk")) + FString OkValue; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SpacetimeDB", meta = (EditCondition = "!bIsOk")) + int32 ErrValue; + + FTestClientResultStringInt32() = default; + + static FTestClientResultStringInt32 Ok(const FString& InValue) + { + FTestClientResultStringInt32 Result; + Result.bIsOk = true; + Result.OkValue = InValue; + return Result; + } + + static FTestClientResultStringInt32 Err(const int32& InValue) + { + FTestClientResultStringInt32 Result; + Result.bIsOk = false; + Result.ErrValue = InValue; + return Result; + } + + bool IsOk() const { return bIsOk; } + bool IsErr() const { return !bIsOk; } + + const FString& GetOk() const + { + check(bIsOk); + return OkValue; + } + + const int32& GetErr() const + { + check(!bIsOk); + return ErrValue; + } + + FORCEINLINE bool operator==(const FTestClientResultStringInt32& Other) const + { + if (bIsOk != Other.bIsOk) return false; + if (bIsOk) + { + return OkValue == Other.OkValue; + } + else + { + return ErrValue == Other.ErrValue; + } + } + + FORCEINLINE bool operator!=(const FTestClientResultStringInt32& Other) const + { + return !(*this == Other); + } +}; + +/** + * Custom hash function for FTestClientResultStringInt32. + * Hashes the bIsOk flag and the appropriate value. + * @param Result The FTestClientResultStringInt32 instance to hash. + * @return The combined hash value. + */ +FORCEINLINE uint32 GetTypeHash(const FTestClientResultStringInt32& Result) +{ + uint32 Hash = GetTypeHash(Result.bIsOk); + if (Result.bIsOk) + { + Hash = HashCombine(Hash, GetTypeHash(Result.OkValue)); + } + else + { + Hash = HashCombine(Hash, GetTypeHash(Result.ErrValue)); + } + return Hash; +} + +namespace UE::SpacetimeDB +{ + UE_SPACETIMEDB_ENABLE_TARRAY(FTestClientResultStringInt32); + + UE_SPACETIMEDB_RESULT(FTestClientResultStringInt32, bIsOk, OkValue, ErrValue); +} diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Results/TestClientResultVecInt32String.g.h b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Results/TestClientResultVecInt32String.g.h new file mode 100644 index 00000000000..92cc0108bd6 --- /dev/null +++ b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Results/TestClientResultVecInt32String.g.h @@ -0,0 +1,100 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#pragma once +#include "CoreMinimal.h" +#include "BSATN/UESpacetimeDB.h" +#include "TestClientResultVecInt32String.g.generated.h" + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FTestClientResultVecInt32String +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SpacetimeDB") + bool bIsOk = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SpacetimeDB", meta = (EditCondition = "bIsOk")) + TArray OkValue; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SpacetimeDB", meta = (EditCondition = "!bIsOk")) + FString ErrValue; + + FTestClientResultVecInt32String() = default; + + static FTestClientResultVecInt32String Ok(const TArray& InValue) + { + FTestClientResultVecInt32String Result; + Result.bIsOk = true; + Result.OkValue = InValue; + return Result; + } + + static FTestClientResultVecInt32String Err(const FString& InValue) + { + FTestClientResultVecInt32String Result; + Result.bIsOk = false; + Result.ErrValue = InValue; + return Result; + } + + bool IsOk() const { return bIsOk; } + bool IsErr() const { return !bIsOk; } + + const TArray& GetOk() const + { + check(bIsOk); + return OkValue; + } + + const FString& GetErr() const + { + check(!bIsOk); + return ErrValue; + } + + FORCEINLINE bool operator==(const FTestClientResultVecInt32String& Other) const + { + if (bIsOk != Other.bIsOk) return false; + if (bIsOk) + { + return OkValue == Other.OkValue; + } + else + { + return ErrValue == Other.ErrValue; + } + } + + FORCEINLINE bool operator!=(const FTestClientResultVecInt32String& Other) const + { + return !(*this == Other); + } +}; + +/** + * Custom hash function for FTestClientResultVecInt32String. + * Hashes the bIsOk flag and the appropriate value. + * @param Result The FTestClientResultVecInt32String instance to hash. + * @return The combined hash value. + */ +FORCEINLINE uint32 GetTypeHash(const FTestClientResultVecInt32String& Result) +{ + uint32 Hash = GetTypeHash(Result.bIsOk); + if (Result.bIsOk) + { + Hash = HashCombine(Hash, GetTypeHash(Result.OkValue)); + } + else + { + Hash = HashCombine(Hash, GetTypeHash(Result.ErrValue)); + } + return Hash; +} + +namespace UE::SpacetimeDB +{ + UE_SPACETIMEDB_ENABLE_TARRAY(FTestClientResultVecInt32String); + + UE_SPACETIMEDB_RESULT(FTestClientResultVecInt32String, bIsOk, OkValue, ErrValue); +} diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/SpacetimeDBClient.g.h b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/SpacetimeDBClient.g.h index 1c8ea7c5302..bbcc32c6907 100644 --- a/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/SpacetimeDBClient.g.h +++ b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/SpacetimeDBClient.g.h @@ -1,7 +1,7 @@ // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE // WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. -// This was generated using spacetimedb cli version 1.8.0 (commit 4d8a5e04dbbe4e58453022d7f69daea291cef863). +// This was generated using spacetimedb cli version 1.10.0 (commit 4324cd74366922cb2df02fffaf7bc268c7044b1f). #pragma once #include "CoreMinimal.h" @@ -118,6 +118,12 @@ #include "ModuleBindings/Reducers/InsertPkU64.g.h" #include "ModuleBindings/Reducers/InsertPkU8.g.h" #include "ModuleBindings/Reducers/InsertPrimitivesAsStrings.g.h" +#include "ModuleBindings/Reducers/InsertResultEveryPrimitiveStructString.g.h" +#include "ModuleBindings/Reducers/InsertResultI32String.g.h" +#include "ModuleBindings/Reducers/InsertResultIdentityString.g.h" +#include "ModuleBindings/Reducers/InsertResultSimpleEnumI32.g.h" +#include "ModuleBindings/Reducers/InsertResultStringI32.g.h" +#include "ModuleBindings/Reducers/InsertResultVecI32String.g.h" #include "ModuleBindings/Reducers/InsertTableHoldsTable.g.h" #include "ModuleBindings/Reducers/InsertUniqueBool.g.h" #include "ModuleBindings/Reducers/InsertUniqueConnectionId.g.h" @@ -199,6 +205,12 @@ #include "ModuleBindings/Reducers/UpdateUniqueU32.g.h" #include "ModuleBindings/Reducers/UpdateUniqueU64.g.h" #include "ModuleBindings/Reducers/UpdateUniqueU8.g.h" +#include "ModuleBindings/Results/TestClientResultEveryPrimitiveStructString.g.h" +#include "ModuleBindings/Results/TestClientResultIdentityString.g.h" +#include "ModuleBindings/Results/TestClientResultInt32String.g.h" +#include "ModuleBindings/Results/TestClientResultSimpleEnumInt32.g.h" +#include "ModuleBindings/Results/TestClientResultStringInt32.g.h" +#include "ModuleBindings/Results/TestClientResultVecInt32String.g.h" #include "ModuleBindings/Types/BTreeU32Type.g.h" #include "ModuleBindings/Types/ByteStructType.g.h" #include "ModuleBindings/Types/EnumWithPayloadType.g.h" @@ -276,6 +288,12 @@ class UPkU32Table; class UPkU32TwoTable; class UPkU64Table; class UPkU8Table; +class UResultEveryPrimitiveStructStringTable; +class UResultI32StringTable; +class UResultIdentityStringTable; +class UResultSimpleEnumI32Table; +class UResultStringI32Table; +class UResultVecI32StringTable; class UScheduledTableTable; class UTableHoldsTableTable; class UUniqueBoolTable; @@ -494,6 +512,12 @@ enum class EReducerTag : uint8 InsertPkU64, InsertPkU8, InsertPrimitivesAsStrings, + InsertResultEveryPrimitiveStructString, + InsertResultI32String, + InsertResultIdentityString, + InsertResultSimpleEnumI32, + InsertResultStringI32, + InsertResultVecI32String, InsertTableHoldsTable, InsertUniqueBool, InsertUniqueConnectionId, @@ -586,7 +610,7 @@ struct TESTCLIENT_API FReducer UPROPERTY(BlueprintReadOnly, Category = "SpacetimeDB") EReducerTag Tag = static_cast(0); - TVariant Data; + TVariant Data; // Optional metadata UPROPERTY(BlueprintReadOnly, Category = "SpacetimeDB") @@ -2178,6 +2202,102 @@ struct TESTCLIENT_API FReducer return Data.Get(); } + static FReducer InsertResultEveryPrimitiveStructString(const FInsertResultEveryPrimitiveStructStringArgs& Value) + { + FReducer Out; + Out.Tag = EReducerTag::InsertResultEveryPrimitiveStructString; + Out.Data.Set(Value); + Out.ReducerName = TEXT("insert_result_every_primitive_struct_string"); + return Out; + } + + FORCEINLINE bool IsInsertResultEveryPrimitiveStructString() const { return Tag == EReducerTag::InsertResultEveryPrimitiveStructString; } + FORCEINLINE FInsertResultEveryPrimitiveStructStringArgs GetAsInsertResultEveryPrimitiveStructString() const + { + ensureMsgf(IsInsertResultEveryPrimitiveStructString(), TEXT("Reducer does not hold InsertResultEveryPrimitiveStructString!")); + return Data.Get(); + } + + static FReducer InsertResultI32String(const FInsertResultI32StringArgs& Value) + { + FReducer Out; + Out.Tag = EReducerTag::InsertResultI32String; + Out.Data.Set(Value); + Out.ReducerName = TEXT("insert_result_i32_string"); + return Out; + } + + FORCEINLINE bool IsInsertResultI32String() const { return Tag == EReducerTag::InsertResultI32String; } + FORCEINLINE FInsertResultI32StringArgs GetAsInsertResultI32String() const + { + ensureMsgf(IsInsertResultI32String(), TEXT("Reducer does not hold InsertResultI32String!")); + return Data.Get(); + } + + static FReducer InsertResultIdentityString(const FInsertResultIdentityStringArgs& Value) + { + FReducer Out; + Out.Tag = EReducerTag::InsertResultIdentityString; + Out.Data.Set(Value); + Out.ReducerName = TEXT("insert_result_identity_string"); + return Out; + } + + FORCEINLINE bool IsInsertResultIdentityString() const { return Tag == EReducerTag::InsertResultIdentityString; } + FORCEINLINE FInsertResultIdentityStringArgs GetAsInsertResultIdentityString() const + { + ensureMsgf(IsInsertResultIdentityString(), TEXT("Reducer does not hold InsertResultIdentityString!")); + return Data.Get(); + } + + static FReducer InsertResultSimpleEnumI32(const FInsertResultSimpleEnumI32Args& Value) + { + FReducer Out; + Out.Tag = EReducerTag::InsertResultSimpleEnumI32; + Out.Data.Set(Value); + Out.ReducerName = TEXT("insert_result_simple_enum_i32"); + return Out; + } + + FORCEINLINE bool IsInsertResultSimpleEnumI32() const { return Tag == EReducerTag::InsertResultSimpleEnumI32; } + FORCEINLINE FInsertResultSimpleEnumI32Args GetAsInsertResultSimpleEnumI32() const + { + ensureMsgf(IsInsertResultSimpleEnumI32(), TEXT("Reducer does not hold InsertResultSimpleEnumI32!")); + return Data.Get(); + } + + static FReducer InsertResultStringI32(const FInsertResultStringI32Args& Value) + { + FReducer Out; + Out.Tag = EReducerTag::InsertResultStringI32; + Out.Data.Set(Value); + Out.ReducerName = TEXT("insert_result_string_i32"); + return Out; + } + + FORCEINLINE bool IsInsertResultStringI32() const { return Tag == EReducerTag::InsertResultStringI32; } + FORCEINLINE FInsertResultStringI32Args GetAsInsertResultStringI32() const + { + ensureMsgf(IsInsertResultStringI32(), TEXT("Reducer does not hold InsertResultStringI32!")); + return Data.Get(); + } + + static FReducer InsertResultVecI32String(const FInsertResultVecI32StringArgs& Value) + { + FReducer Out; + Out.Tag = EReducerTag::InsertResultVecI32String; + Out.Data.Set(Value); + Out.ReducerName = TEXT("insert_result_vec_i32_string"); + return Out; + } + + FORCEINLINE bool IsInsertResultVecI32String() const { return Tag == EReducerTag::InsertResultVecI32String; } + FORCEINLINE FInsertResultVecI32StringArgs GetAsInsertResultVecI32String() const + { + ensureMsgf(IsInsertResultVecI32String(), TEXT("Reducer does not hold InsertResultVecI32String!")); + return Data.Get(); + } + static FReducer InsertTableHoldsTable(const FInsertTableHoldsTableArgs& Value) { FReducer Out; @@ -3677,6 +3797,18 @@ struct TESTCLIENT_API FReducer return GetAsInsertPkU8() == Other.GetAsInsertPkU8(); case EReducerTag::InsertPrimitivesAsStrings: return GetAsInsertPrimitivesAsStrings() == Other.GetAsInsertPrimitivesAsStrings(); + case EReducerTag::InsertResultEveryPrimitiveStructString: + return GetAsInsertResultEveryPrimitiveStructString() == Other.GetAsInsertResultEveryPrimitiveStructString(); + case EReducerTag::InsertResultI32String: + return GetAsInsertResultI32String() == Other.GetAsInsertResultI32String(); + case EReducerTag::InsertResultIdentityString: + return GetAsInsertResultIdentityString() == Other.GetAsInsertResultIdentityString(); + case EReducerTag::InsertResultSimpleEnumI32: + return GetAsInsertResultSimpleEnumI32() == Other.GetAsInsertResultSimpleEnumI32(); + case EReducerTag::InsertResultStringI32: + return GetAsInsertResultStringI32() == Other.GetAsInsertResultStringI32(); + case EReducerTag::InsertResultVecI32String: + return GetAsInsertResultVecI32String() == Other.GetAsInsertResultVecI32String(); case EReducerTag::InsertTableHoldsTable: return GetAsInsertTableHoldsTable() == Other.GetAsInsertTableHoldsTable(); case EReducerTag::InsertUniqueBool: @@ -5139,6 +5271,84 @@ class TESTCLIENT_API UReducerBpLib : public UBlueprintFunctionLibrary return Reducer.GetAsInsertPrimitivesAsStrings(); } + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB|Reducer") + static FReducer InsertResultEveryPrimitiveStructString(const FInsertResultEveryPrimitiveStructStringArgs& Value) { + return FReducer::InsertResultEveryPrimitiveStructString(Value); + } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|Reducer") + static bool IsInsertResultEveryPrimitiveStructString(const FReducer& Reducer) { return Reducer.IsInsertResultEveryPrimitiveStructString(); } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|Reducer") + static FInsertResultEveryPrimitiveStructStringArgs GetAsInsertResultEveryPrimitiveStructString(const FReducer& Reducer) { + return Reducer.GetAsInsertResultEveryPrimitiveStructString(); + } + + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB|Reducer") + static FReducer InsertResultI32String(const FInsertResultI32StringArgs& Value) { + return FReducer::InsertResultI32String(Value); + } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|Reducer") + static bool IsInsertResultI32String(const FReducer& Reducer) { return Reducer.IsInsertResultI32String(); } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|Reducer") + static FInsertResultI32StringArgs GetAsInsertResultI32String(const FReducer& Reducer) { + return Reducer.GetAsInsertResultI32String(); + } + + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB|Reducer") + static FReducer InsertResultIdentityString(const FInsertResultIdentityStringArgs& Value) { + return FReducer::InsertResultIdentityString(Value); + } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|Reducer") + static bool IsInsertResultIdentityString(const FReducer& Reducer) { return Reducer.IsInsertResultIdentityString(); } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|Reducer") + static FInsertResultIdentityStringArgs GetAsInsertResultIdentityString(const FReducer& Reducer) { + return Reducer.GetAsInsertResultIdentityString(); + } + + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB|Reducer") + static FReducer InsertResultSimpleEnumI32(const FInsertResultSimpleEnumI32Args& Value) { + return FReducer::InsertResultSimpleEnumI32(Value); + } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|Reducer") + static bool IsInsertResultSimpleEnumI32(const FReducer& Reducer) { return Reducer.IsInsertResultSimpleEnumI32(); } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|Reducer") + static FInsertResultSimpleEnumI32Args GetAsInsertResultSimpleEnumI32(const FReducer& Reducer) { + return Reducer.GetAsInsertResultSimpleEnumI32(); + } + + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB|Reducer") + static FReducer InsertResultStringI32(const FInsertResultStringI32Args& Value) { + return FReducer::InsertResultStringI32(Value); + } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|Reducer") + static bool IsInsertResultStringI32(const FReducer& Reducer) { return Reducer.IsInsertResultStringI32(); } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|Reducer") + static FInsertResultStringI32Args GetAsInsertResultStringI32(const FReducer& Reducer) { + return Reducer.GetAsInsertResultStringI32(); + } + + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB|Reducer") + static FReducer InsertResultVecI32String(const FInsertResultVecI32StringArgs& Value) { + return FReducer::InsertResultVecI32String(Value); + } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|Reducer") + static bool IsInsertResultVecI32String(const FReducer& Reducer) { return Reducer.IsInsertResultVecI32String(); } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|Reducer") + static FInsertResultVecI32StringArgs GetAsInsertResultVecI32String(const FReducer& Reducer) { + return Reducer.GetAsInsertResultVecI32String(); + } + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB|Reducer") static FReducer InsertTableHoldsTable(const FInsertTableHoldsTableArgs& Value) { return FReducer::InsertTableHoldsTable(Value); @@ -6770,6 +6980,18 @@ class TESTCLIENT_API USetReducerFlags : public USetReducerFlagsBase UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") void InsertPrimitivesAsStrings(ECallReducerFlags Flag); UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + void InsertResultEveryPrimitiveStructString(ECallReducerFlags Flag); + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + void InsertResultI32String(ECallReducerFlags Flag); + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + void InsertResultIdentityString(ECallReducerFlags Flag); + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + void InsertResultSimpleEnumI32(ECallReducerFlags Flag); + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + void InsertResultStringI32(ECallReducerFlags Flag); + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + void InsertResultVecI32String(ECallReducerFlags Flag); + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") void InsertTableHoldsTable(ECallReducerFlags Flag); UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") void InsertUniqueBool(ECallReducerFlags Flag); @@ -7105,6 +7327,24 @@ class TESTCLIENT_API URemoteTables : public UObject UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") UPkU8Table* PkU8; + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + UResultEveryPrimitiveStructStringTable* ResultEveryPrimitiveStructString; + + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + UResultI32StringTable* ResultI32String; + + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + UResultIdentityStringTable* ResultIdentityString; + + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + UResultSimpleEnumI32Table* ResultSimpleEnumI32; + + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + UResultStringI32Table* ResultStringI32; + + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + UResultVecI32StringTable* ResultVecI32String; + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") UScheduledTableTable* ScheduledTable; @@ -8549,6 +8789,84 @@ class TESTCLIENT_API URemoteReducers : public UObject bool InvokeInsertPrimitivesAsStrings(const FReducerEventContext& Context, const UInsertPrimitivesAsStringsReducer* Args); + DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( + FInsertResultEveryPrimitiveStructStringHandler, + const FReducerEventContext&, Context, + const FTestClientResultEveryPrimitiveStructString&, R + ); + UPROPERTY(BlueprintAssignable, Category="SpacetimeDB") + FInsertResultEveryPrimitiveStructStringHandler OnInsertResultEveryPrimitiveStructString; + + UFUNCTION(BlueprintCallable, Category="SpacetimeDB") + void InsertResultEveryPrimitiveStructString(const FTestClientResultEveryPrimitiveStructString& R); + + bool InvokeInsertResultEveryPrimitiveStructString(const FReducerEventContext& Context, const UInsertResultEveryPrimitiveStructStringReducer* Args); + + DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( + FInsertResultI32StringHandler, + const FReducerEventContext&, Context, + const FTestClientResultInt32String&, R + ); + UPROPERTY(BlueprintAssignable, Category="SpacetimeDB") + FInsertResultI32StringHandler OnInsertResultI32String; + + UFUNCTION(BlueprintCallable, Category="SpacetimeDB") + void InsertResultI32String(const FTestClientResultInt32String& R); + + bool InvokeInsertResultI32String(const FReducerEventContext& Context, const UInsertResultI32StringReducer* Args); + + DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( + FInsertResultIdentityStringHandler, + const FReducerEventContext&, Context, + const FTestClientResultIdentityString&, R + ); + UPROPERTY(BlueprintAssignable, Category="SpacetimeDB") + FInsertResultIdentityStringHandler OnInsertResultIdentityString; + + UFUNCTION(BlueprintCallable, Category="SpacetimeDB") + void InsertResultIdentityString(const FTestClientResultIdentityString& R); + + bool InvokeInsertResultIdentityString(const FReducerEventContext& Context, const UInsertResultIdentityStringReducer* Args); + + DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( + FInsertResultSimpleEnumI32Handler, + const FReducerEventContext&, Context, + const FTestClientResultSimpleEnumInt32&, R + ); + UPROPERTY(BlueprintAssignable, Category="SpacetimeDB") + FInsertResultSimpleEnumI32Handler OnInsertResultSimpleEnumI32; + + UFUNCTION(BlueprintCallable, Category="SpacetimeDB") + void InsertResultSimpleEnumI32(const FTestClientResultSimpleEnumInt32& R); + + bool InvokeInsertResultSimpleEnumI32(const FReducerEventContext& Context, const UInsertResultSimpleEnumI32Reducer* Args); + + DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( + FInsertResultStringI32Handler, + const FReducerEventContext&, Context, + const FTestClientResultStringInt32&, R + ); + UPROPERTY(BlueprintAssignable, Category="SpacetimeDB") + FInsertResultStringI32Handler OnInsertResultStringI32; + + UFUNCTION(BlueprintCallable, Category="SpacetimeDB") + void InsertResultStringI32(const FTestClientResultStringInt32& R); + + bool InvokeInsertResultStringI32(const FReducerEventContext& Context, const UInsertResultStringI32Reducer* Args); + + DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( + FInsertResultVecI32StringHandler, + const FReducerEventContext&, Context, + const FTestClientResultVecInt32String&, R + ); + UPROPERTY(BlueprintAssignable, Category="SpacetimeDB") + FInsertResultVecI32StringHandler OnInsertResultVecI32String; + + UFUNCTION(BlueprintCallable, Category="SpacetimeDB") + void InsertResultVecI32String(const FTestClientResultVecInt32String& R); + + bool InvokeInsertResultVecI32String(const FReducerEventContext& Context, const UInsertResultVecI32StringReducer* Args); + DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams( FInsertTableHoldsTableHandler, const FReducerEventContext&, Context, diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Tables/ResultEveryPrimitiveStructStringTable.g.h b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Tables/ResultEveryPrimitiveStructStringTable.g.h new file mode 100644 index 00000000000..5ddb516f2b1 --- /dev/null +++ b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Tables/ResultEveryPrimitiveStructStringTable.g.h @@ -0,0 +1,64 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#pragma once +#include "CoreMinimal.h" +#include "BSATN/UESpacetimeDB.h" +#include "Types/Builtins.h" +#include "ModuleBindings/Types/ResultEveryPrimitiveStructStringType.g.h" +#include "Tables/RemoteTable.h" +#include "DBCache/WithBsatn.h" +#include "DBCache/TableHandle.h" +#include "DBCache/TableCache.h" +#include "ResultEveryPrimitiveStructStringTable.g.generated.h" + +UCLASS(BlueprintType) +class TESTCLIENT_API UResultEveryPrimitiveStructStringTable : public URemoteTable +{ + GENERATED_BODY() + +public: + void PostInitialize(); + + /** Update function for result_every_primitive_struct_string table*/ + FTableAppliedDiff Update(TArray> InsertsRef, TArray> DeletesRef); + + /** Number of subscribed rows currently in the cache */ + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + int32 Count() const; + + /** Return all subscribed rows in the cache */ + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + TArray Iter() const; + + // Table Events + DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( + FOnResultEveryPrimitiveStructStringInsert, + const FEventContext&, Context, + const FResultEveryPrimitiveStructStringType&, NewRow); + + DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams( + FOnResultEveryPrimitiveStructStringUpdate, + const FEventContext&, Context, + const FResultEveryPrimitiveStructStringType&, OldRow, + const FResultEveryPrimitiveStructStringType&, NewRow); + + DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( + FOnResultEveryPrimitiveStructStringDelete, + const FEventContext&, Context, + const FResultEveryPrimitiveStructStringType&, DeletedRow); + + UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") + FOnResultEveryPrimitiveStructStringInsert OnInsert; + + UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") + FOnResultEveryPrimitiveStructStringUpdate OnUpdate; + + UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") + FOnResultEveryPrimitiveStructStringDelete OnDelete; + +private: + const FString TableName = TEXT("result_every_primitive_struct_string"); + + TSharedPtr> Data; +}; diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Tables/ResultI32StringTable.g.h b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Tables/ResultI32StringTable.g.h new file mode 100644 index 00000000000..89b91d58575 --- /dev/null +++ b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Tables/ResultI32StringTable.g.h @@ -0,0 +1,64 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#pragma once +#include "CoreMinimal.h" +#include "BSATN/UESpacetimeDB.h" +#include "Types/Builtins.h" +#include "ModuleBindings/Types/ResultI32StringType.g.h" +#include "Tables/RemoteTable.h" +#include "DBCache/WithBsatn.h" +#include "DBCache/TableHandle.h" +#include "DBCache/TableCache.h" +#include "ResultI32StringTable.g.generated.h" + +UCLASS(BlueprintType) +class TESTCLIENT_API UResultI32StringTable : public URemoteTable +{ + GENERATED_BODY() + +public: + void PostInitialize(); + + /** Update function for result_i32_string table*/ + FTableAppliedDiff Update(TArray> InsertsRef, TArray> DeletesRef); + + /** Number of subscribed rows currently in the cache */ + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + int32 Count() const; + + /** Return all subscribed rows in the cache */ + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + TArray Iter() const; + + // Table Events + DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( + FOnResultI32StringInsert, + const FEventContext&, Context, + const FResultI32StringType&, NewRow); + + DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams( + FOnResultI32StringUpdate, + const FEventContext&, Context, + const FResultI32StringType&, OldRow, + const FResultI32StringType&, NewRow); + + DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( + FOnResultI32StringDelete, + const FEventContext&, Context, + const FResultI32StringType&, DeletedRow); + + UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") + FOnResultI32StringInsert OnInsert; + + UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") + FOnResultI32StringUpdate OnUpdate; + + UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") + FOnResultI32StringDelete OnDelete; + +private: + const FString TableName = TEXT("result_i32_string"); + + TSharedPtr> Data; +}; diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Tables/ResultIdentityStringTable.g.h b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Tables/ResultIdentityStringTable.g.h new file mode 100644 index 00000000000..8138a7305aa --- /dev/null +++ b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Tables/ResultIdentityStringTable.g.h @@ -0,0 +1,64 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#pragma once +#include "CoreMinimal.h" +#include "BSATN/UESpacetimeDB.h" +#include "Types/Builtins.h" +#include "ModuleBindings/Types/ResultIdentityStringType.g.h" +#include "Tables/RemoteTable.h" +#include "DBCache/WithBsatn.h" +#include "DBCache/TableHandle.h" +#include "DBCache/TableCache.h" +#include "ResultIdentityStringTable.g.generated.h" + +UCLASS(BlueprintType) +class TESTCLIENT_API UResultIdentityStringTable : public URemoteTable +{ + GENERATED_BODY() + +public: + void PostInitialize(); + + /** Update function for result_identity_string table*/ + FTableAppliedDiff Update(TArray> InsertsRef, TArray> DeletesRef); + + /** Number of subscribed rows currently in the cache */ + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + int32 Count() const; + + /** Return all subscribed rows in the cache */ + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + TArray Iter() const; + + // Table Events + DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( + FOnResultIdentityStringInsert, + const FEventContext&, Context, + const FResultIdentityStringType&, NewRow); + + DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams( + FOnResultIdentityStringUpdate, + const FEventContext&, Context, + const FResultIdentityStringType&, OldRow, + const FResultIdentityStringType&, NewRow); + + DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( + FOnResultIdentityStringDelete, + const FEventContext&, Context, + const FResultIdentityStringType&, DeletedRow); + + UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") + FOnResultIdentityStringInsert OnInsert; + + UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") + FOnResultIdentityStringUpdate OnUpdate; + + UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") + FOnResultIdentityStringDelete OnDelete; + +private: + const FString TableName = TEXT("result_identity_string"); + + TSharedPtr> Data; +}; diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Tables/ResultSimpleEnumI32Table.g.h b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Tables/ResultSimpleEnumI32Table.g.h new file mode 100644 index 00000000000..793cdb36fc6 --- /dev/null +++ b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Tables/ResultSimpleEnumI32Table.g.h @@ -0,0 +1,64 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#pragma once +#include "CoreMinimal.h" +#include "BSATN/UESpacetimeDB.h" +#include "Types/Builtins.h" +#include "ModuleBindings/Types/ResultSimpleEnumI32Type.g.h" +#include "Tables/RemoteTable.h" +#include "DBCache/WithBsatn.h" +#include "DBCache/TableHandle.h" +#include "DBCache/TableCache.h" +#include "ResultSimpleEnumI32Table.g.generated.h" + +UCLASS(BlueprintType) +class TESTCLIENT_API UResultSimpleEnumI32Table : public URemoteTable +{ + GENERATED_BODY() + +public: + void PostInitialize(); + + /** Update function for result_simple_enum_i32 table*/ + FTableAppliedDiff Update(TArray> InsertsRef, TArray> DeletesRef); + + /** Number of subscribed rows currently in the cache */ + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + int32 Count() const; + + /** Return all subscribed rows in the cache */ + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + TArray Iter() const; + + // Table Events + DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( + FOnResultSimpleEnumI32Insert, + const FEventContext&, Context, + const FResultSimpleEnumI32Type&, NewRow); + + DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams( + FOnResultSimpleEnumI32Update, + const FEventContext&, Context, + const FResultSimpleEnumI32Type&, OldRow, + const FResultSimpleEnumI32Type&, NewRow); + + DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( + FOnResultSimpleEnumI32Delete, + const FEventContext&, Context, + const FResultSimpleEnumI32Type&, DeletedRow); + + UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") + FOnResultSimpleEnumI32Insert OnInsert; + + UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") + FOnResultSimpleEnumI32Update OnUpdate; + + UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") + FOnResultSimpleEnumI32Delete OnDelete; + +private: + const FString TableName = TEXT("result_simple_enum_i32"); + + TSharedPtr> Data; +}; diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Tables/ResultStringI32Table.g.h b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Tables/ResultStringI32Table.g.h new file mode 100644 index 00000000000..f1b5903f9e0 --- /dev/null +++ b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Tables/ResultStringI32Table.g.h @@ -0,0 +1,64 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#pragma once +#include "CoreMinimal.h" +#include "BSATN/UESpacetimeDB.h" +#include "Types/Builtins.h" +#include "ModuleBindings/Types/ResultStringI32Type.g.h" +#include "Tables/RemoteTable.h" +#include "DBCache/WithBsatn.h" +#include "DBCache/TableHandle.h" +#include "DBCache/TableCache.h" +#include "ResultStringI32Table.g.generated.h" + +UCLASS(BlueprintType) +class TESTCLIENT_API UResultStringI32Table : public URemoteTable +{ + GENERATED_BODY() + +public: + void PostInitialize(); + + /** Update function for result_string_i32 table*/ + FTableAppliedDiff Update(TArray> InsertsRef, TArray> DeletesRef); + + /** Number of subscribed rows currently in the cache */ + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + int32 Count() const; + + /** Return all subscribed rows in the cache */ + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + TArray Iter() const; + + // Table Events + DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( + FOnResultStringI32Insert, + const FEventContext&, Context, + const FResultStringI32Type&, NewRow); + + DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams( + FOnResultStringI32Update, + const FEventContext&, Context, + const FResultStringI32Type&, OldRow, + const FResultStringI32Type&, NewRow); + + DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( + FOnResultStringI32Delete, + const FEventContext&, Context, + const FResultStringI32Type&, DeletedRow); + + UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") + FOnResultStringI32Insert OnInsert; + + UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") + FOnResultStringI32Update OnUpdate; + + UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") + FOnResultStringI32Delete OnDelete; + +private: + const FString TableName = TEXT("result_string_i32"); + + TSharedPtr> Data; +}; diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Tables/ResultVecI32StringTable.g.h b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Tables/ResultVecI32StringTable.g.h new file mode 100644 index 00000000000..cfe2096b6ab --- /dev/null +++ b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Tables/ResultVecI32StringTable.g.h @@ -0,0 +1,64 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#pragma once +#include "CoreMinimal.h" +#include "BSATN/UESpacetimeDB.h" +#include "Types/Builtins.h" +#include "ModuleBindings/Types/ResultVecI32StringType.g.h" +#include "Tables/RemoteTable.h" +#include "DBCache/WithBsatn.h" +#include "DBCache/TableHandle.h" +#include "DBCache/TableCache.h" +#include "ResultVecI32StringTable.g.generated.h" + +UCLASS(BlueprintType) +class TESTCLIENT_API UResultVecI32StringTable : public URemoteTable +{ + GENERATED_BODY() + +public: + void PostInitialize(); + + /** Update function for result_vec_i32_string table*/ + FTableAppliedDiff Update(TArray> InsertsRef, TArray> DeletesRef); + + /** Number of subscribed rows currently in the cache */ + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + int32 Count() const; + + /** Return all subscribed rows in the cache */ + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + TArray Iter() const; + + // Table Events + DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( + FOnResultVecI32StringInsert, + const FEventContext&, Context, + const FResultVecI32StringType&, NewRow); + + DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams( + FOnResultVecI32StringUpdate, + const FEventContext&, Context, + const FResultVecI32StringType&, OldRow, + const FResultVecI32StringType&, NewRow); + + DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( + FOnResultVecI32StringDelete, + const FEventContext&, Context, + const FResultVecI32StringType&, DeletedRow); + + UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") + FOnResultVecI32StringInsert OnInsert; + + UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") + FOnResultVecI32StringUpdate OnUpdate; + + UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") + FOnResultVecI32StringDelete OnDelete; + +private: + const FString TableName = TEXT("result_vec_i32_string"); + + TSharedPtr> Data; +}; diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Types/EnumWithPayloadType.g.h b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Types/EnumWithPayloadType.g.h index 560693ddb4c..78518c60ab2 100644 --- a/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Types/EnumWithPayloadType.g.h +++ b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Types/EnumWithPayloadType.g.h @@ -45,7 +45,7 @@ struct TESTCLIENT_API FEnumWithPayloadType public: FEnumWithPayloadType() = default; - TVariant, uint32, FString, FSpacetimeDBInt128, TArray, uint64, FSpacetimeDBConnectionId, TArray, int64, FSpacetimeDBUInt128, int32, float, int8, uint16, FSpacetimeDBIdentity, FSpacetimeDBUInt256, TArray, bool, FSpacetimeDBTimestamp, uint8, FSpacetimeDBInt256> MessageData; + TVariant, FSpacetimeDBIdentity, TArray, uint8, FSpacetimeDBInt128, double, int8, TArray, int32, int64, bool, uint32, uint16, TArray, uint64, FSpacetimeDBTimestamp, int16, float, FString, FSpacetimeDBUInt256, FSpacetimeDBUInt128, FSpacetimeDBInt256, FSpacetimeDBConnectionId> MessageData; UPROPERTY(BlueprintReadOnly) EEnumWithPayloadTag Tag = static_cast(0); diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Types/ResultEveryPrimitiveStructStringType.g.h b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Types/ResultEveryPrimitiveStructStringType.g.h new file mode 100644 index 00000000000..beccd2e7a69 --- /dev/null +++ b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Types/ResultEveryPrimitiveStructStringType.g.h @@ -0,0 +1,47 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#pragma once +#include "CoreMinimal.h" +#include "BSATN/UESpacetimeDB.h" +#include "ModuleBindings/Results/TestClientResultEveryPrimitiveStructString.g.h" +#include "ModuleBindings/Types/EveryPrimitiveStructType.g.h" +#include "ResultEveryPrimitiveStructStringType.g.generated.h" + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FResultEveryPrimitiveStructStringType +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SpacetimeDB") + FTestClientResultEveryPrimitiveStructString R; + + FORCEINLINE bool operator==(const FResultEveryPrimitiveStructStringType& Other) const + { + return R == Other.R; + } + + FORCEINLINE bool operator!=(const FResultEveryPrimitiveStructStringType& Other) const + { + return !(*this == Other); + } +}; + +/** + * Custom hash function for FResultEveryPrimitiveStructStringType. + * Combines the hashes of all fields that are compared in operator==. + * @param ResultEveryPrimitiveStructStringType The FResultEveryPrimitiveStructStringType instance to hash. + * @return The combined hash value. + */ +FORCEINLINE uint32 GetTypeHash(const FResultEveryPrimitiveStructStringType& ResultEveryPrimitiveStructStringType) +{ + uint32 Hash = GetTypeHash(ResultEveryPrimitiveStructStringType.R); + return Hash; +} + +namespace UE::SpacetimeDB +{ + UE_SPACETIMEDB_ENABLE_TARRAY(FResultEveryPrimitiveStructStringType); + + UE_SPACETIMEDB_STRUCT(FResultEveryPrimitiveStructStringType, R); +} diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Types/ResultI32StringType.g.h b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Types/ResultI32StringType.g.h new file mode 100644 index 00000000000..75c43422865 --- /dev/null +++ b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Types/ResultI32StringType.g.h @@ -0,0 +1,46 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#pragma once +#include "CoreMinimal.h" +#include "BSATN/UESpacetimeDB.h" +#include "ModuleBindings/Results/TestClientResultInt32String.g.h" +#include "ResultI32StringType.g.generated.h" + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FResultI32StringType +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SpacetimeDB") + FTestClientResultInt32String R; + + FORCEINLINE bool operator==(const FResultI32StringType& Other) const + { + return R == Other.R; + } + + FORCEINLINE bool operator!=(const FResultI32StringType& Other) const + { + return !(*this == Other); + } +}; + +/** + * Custom hash function for FResultI32StringType. + * Combines the hashes of all fields that are compared in operator==. + * @param ResultI32StringType The FResultI32StringType instance to hash. + * @return The combined hash value. + */ +FORCEINLINE uint32 GetTypeHash(const FResultI32StringType& ResultI32StringType) +{ + uint32 Hash = GetTypeHash(ResultI32StringType.R); + return Hash; +} + +namespace UE::SpacetimeDB +{ + UE_SPACETIMEDB_ENABLE_TARRAY(FResultI32StringType); + + UE_SPACETIMEDB_STRUCT(FResultI32StringType, R); +} diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Types/ResultIdentityStringType.g.h b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Types/ResultIdentityStringType.g.h new file mode 100644 index 00000000000..65c1a874139 --- /dev/null +++ b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Types/ResultIdentityStringType.g.h @@ -0,0 +1,47 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#pragma once +#include "CoreMinimal.h" +#include "BSATN/UESpacetimeDB.h" +#include "ModuleBindings/Results/TestClientResultIdentityString.g.h" +#include "Types/Builtins.h" +#include "ResultIdentityStringType.g.generated.h" + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FResultIdentityStringType +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SpacetimeDB") + FTestClientResultIdentityString R; + + FORCEINLINE bool operator==(const FResultIdentityStringType& Other) const + { + return R == Other.R; + } + + FORCEINLINE bool operator!=(const FResultIdentityStringType& Other) const + { + return !(*this == Other); + } +}; + +/** + * Custom hash function for FResultIdentityStringType. + * Combines the hashes of all fields that are compared in operator==. + * @param ResultIdentityStringType The FResultIdentityStringType instance to hash. + * @return The combined hash value. + */ +FORCEINLINE uint32 GetTypeHash(const FResultIdentityStringType& ResultIdentityStringType) +{ + uint32 Hash = GetTypeHash(ResultIdentityStringType.R); + return Hash; +} + +namespace UE::SpacetimeDB +{ + UE_SPACETIMEDB_ENABLE_TARRAY(FResultIdentityStringType); + + UE_SPACETIMEDB_STRUCT(FResultIdentityStringType, R); +} diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Types/ResultSimpleEnumI32Type.g.h b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Types/ResultSimpleEnumI32Type.g.h new file mode 100644 index 00000000000..348a715c1f9 --- /dev/null +++ b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Types/ResultSimpleEnumI32Type.g.h @@ -0,0 +1,47 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#pragma once +#include "CoreMinimal.h" +#include "BSATN/UESpacetimeDB.h" +#include "ModuleBindings/Results/TestClientResultSimpleEnumInt32.g.h" +#include "ModuleBindings/Types/SimpleEnumType.g.h" +#include "ResultSimpleEnumI32Type.g.generated.h" + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FResultSimpleEnumI32Type +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SpacetimeDB") + FTestClientResultSimpleEnumInt32 R; + + FORCEINLINE bool operator==(const FResultSimpleEnumI32Type& Other) const + { + return R == Other.R; + } + + FORCEINLINE bool operator!=(const FResultSimpleEnumI32Type& Other) const + { + return !(*this == Other); + } +}; + +/** + * Custom hash function for FResultSimpleEnumI32Type. + * Combines the hashes of all fields that are compared in operator==. + * @param ResultSimpleEnumI32Type The FResultSimpleEnumI32Type instance to hash. + * @return The combined hash value. + */ +FORCEINLINE uint32 GetTypeHash(const FResultSimpleEnumI32Type& ResultSimpleEnumI32Type) +{ + uint32 Hash = GetTypeHash(ResultSimpleEnumI32Type.R); + return Hash; +} + +namespace UE::SpacetimeDB +{ + UE_SPACETIMEDB_ENABLE_TARRAY(FResultSimpleEnumI32Type); + + UE_SPACETIMEDB_STRUCT(FResultSimpleEnumI32Type, R); +} diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Types/ResultStringI32Type.g.h b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Types/ResultStringI32Type.g.h new file mode 100644 index 00000000000..1108b0914e8 --- /dev/null +++ b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Types/ResultStringI32Type.g.h @@ -0,0 +1,46 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#pragma once +#include "CoreMinimal.h" +#include "BSATN/UESpacetimeDB.h" +#include "ModuleBindings/Results/TestClientResultStringInt32.g.h" +#include "ResultStringI32Type.g.generated.h" + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FResultStringI32Type +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SpacetimeDB") + FTestClientResultStringInt32 R; + + FORCEINLINE bool operator==(const FResultStringI32Type& Other) const + { + return R == Other.R; + } + + FORCEINLINE bool operator!=(const FResultStringI32Type& Other) const + { + return !(*this == Other); + } +}; + +/** + * Custom hash function for FResultStringI32Type. + * Combines the hashes of all fields that are compared in operator==. + * @param ResultStringI32Type The FResultStringI32Type instance to hash. + * @return The combined hash value. + */ +FORCEINLINE uint32 GetTypeHash(const FResultStringI32Type& ResultStringI32Type) +{ + uint32 Hash = GetTypeHash(ResultStringI32Type.R); + return Hash; +} + +namespace UE::SpacetimeDB +{ + UE_SPACETIMEDB_ENABLE_TARRAY(FResultStringI32Type); + + UE_SPACETIMEDB_STRUCT(FResultStringI32Type, R); +} diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Types/ResultVecI32StringType.g.h b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Types/ResultVecI32StringType.g.h new file mode 100644 index 00000000000..4e19f9c857d --- /dev/null +++ b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Types/ResultVecI32StringType.g.h @@ -0,0 +1,46 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#pragma once +#include "CoreMinimal.h" +#include "BSATN/UESpacetimeDB.h" +#include "ModuleBindings/Results/TestClientResultVecInt32String.g.h" +#include "ResultVecI32StringType.g.generated.h" + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FResultVecI32StringType +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SpacetimeDB") + FTestClientResultVecInt32String R; + + FORCEINLINE bool operator==(const FResultVecI32StringType& Other) const + { + return R == Other.R; + } + + FORCEINLINE bool operator!=(const FResultVecI32StringType& Other) const + { + return !(*this == Other); + } +}; + +/** + * Custom hash function for FResultVecI32StringType. + * Combines the hashes of all fields that are compared in operator==. + * @param ResultVecI32StringType The FResultVecI32StringType instance to hash. + * @return The combined hash value. + */ +FORCEINLINE uint32 GetTypeHash(const FResultVecI32StringType& ResultVecI32StringType) +{ + uint32 Hash = GetTypeHash(ResultVecI32StringType.R); + return Hash; +} + +namespace UE::SpacetimeDB +{ + UE_SPACETIMEDB_ENABLE_TARRAY(FResultVecI32StringType); + + UE_SPACETIMEDB_STRUCT(FResultVecI32StringType, R); +} diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Public/Tests/SpacetimeFullClientTests.h b/sdks/unreal/tests/TestClient/Source/TestClient/Public/Tests/SpacetimeFullClientTests.h index c0a4440cd6a..4e3ac300ce1 100644 --- a/sdks/unreal/tests/TestClient/Source/TestClient/Public/Tests/SpacetimeFullClientTests.h +++ b/sdks/unreal/tests/TestClient/Source/TestClient/Public/Tests/SpacetimeFullClientTests.h @@ -65,6 +65,12 @@ IMPLEMENT_SIMPLE_AUTOMATION_TEST(FInsertVecTest, "SpacetimeDB.TestClient.InsertV IMPLEMENT_SIMPLE_AUTOMATION_TEST(FInsertOptionSomeTest, "SpacetimeDB.TestClient.InsertOptionSomeTest", EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter) /** Tests inserting none optional types. */ IMPLEMENT_SIMPLE_AUTOMATION_TEST(FInsertOptionNoneTest, "SpacetimeDB.TestClient.InsertOptionNoneTest", EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter) + +/** Tests inserting Result Ok types. */ +IMPLEMENT_SIMPLE_AUTOMATION_TEST(FInsertResultOkTest, "SpacetimeDB.TestClient.InsertResultOkTest", EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter) +/** Tests inserting Result Err types. */ +//IMPLEMENT_SIMPLE_AUTOMATION_TEST(FInsertResultErrTest, "SpacetimeDB.TestClient.InsertResultErrTest", EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter) + /** Tests inserting struct types. */ IMPLEMENT_SIMPLE_AUTOMATION_TEST(FInsertStructTest, "SpacetimeDB.TestClient.InsertStructTest", EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter) /** Tests inserting simple enum types. */ diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Public/Tests/TestHandler.h b/sdks/unreal/tests/TestClient/Source/TestClient/Public/Tests/TestHandler.h index 6d060fa8c7e..cf82fa48f67 100644 --- a/sdks/unreal/tests/TestClient/Source/TestClient/Public/Tests/TestHandler.h +++ b/sdks/unreal/tests/TestClient/Source/TestClient/Public/Tests/TestHandler.h @@ -386,6 +386,26 @@ class UOptionActionsHandler : public UTestHandler FTestClientOptionalVecOptionalInt32 ExpectedVecOptionI32Type; }; +UCLASS() +class UResultActionsHandler : public UTestHandler +{ + GENERATED_BODY() +public: + UFUNCTION() void OnInsertResultI32String(const FEventContext& Context, const FResultI32StringType& Value); + UFUNCTION() void OnInsertResultStringI32(const FEventContext& Context, const FResultStringI32Type& Value); + UFUNCTION() void OnInsertResultIdentityString(const FEventContext& Context, const FResultIdentityStringType& Value); + UFUNCTION() void OnInsertResultSimpleEnumI32(const FEventContext& Context, const FResultSimpleEnumI32Type& Value); + UFUNCTION() void OnInsertResultEveryPrimitiveStructString(const FEventContext& Context, const FResultEveryPrimitiveStructStringType& Value); + UFUNCTION() void OnInsertResultVecI32String(const FEventContext& Context, const FResultVecI32StringType& Value); + + FTestClientResultInt32String ExpectedResultI32StringType; + FTestClientResultStringInt32 ExpectedResultStringI32Type; + FTestClientResultIdentityString ExpectedResultIdentityStringType; + FTestClientResultSimpleEnumInt32 ExpectedResultSimpleEnumI32Type; + FTestClientResultEveryPrimitiveStructString ExpectedResultEveryPrimitiveStructStringType; + FTestClientResultVecInt32String ExpectedResultVecI32StringType; +}; + UCLASS() class UStructActionsHandler : public UTestHandler { diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Public/Tests/UmbreallaHeaderTypes.h b/sdks/unreal/tests/TestClient/Source/TestClient/Public/Tests/UmbreallaHeaderTypes.h index fc83193de5e..de5ef6bba90 100644 --- a/sdks/unreal/tests/TestClient/Source/TestClient/Public/Tests/UmbreallaHeaderTypes.h +++ b/sdks/unreal/tests/TestClient/Source/TestClient/Public/Tests/UmbreallaHeaderTypes.h @@ -57,6 +57,12 @@ #include "ModuleBindings/Types/PkU32Type.g.h" #include "ModuleBindings/Types/PkU64Type.g.h" #include "ModuleBindings/Types/PkU8Type.g.h" +#include "ModuleBindings/Types/ResultEveryPrimitiveStructStringType.g.h" +#include "ModuleBindings/Types/ResultI32StringType.g.h" +#include "ModuleBindings/Types/ResultIdentityStringType.g.h" +#include "ModuleBindings/Types/ResultSimpleEnumI32Type.g.h" +#include "ModuleBindings/Types/ResultStringI32Type.g.h" +#include "ModuleBindings/Types/ResultVecI32StringType.g.h" #include "ModuleBindings/Types/ScheduledTableType.g.h" #include "ModuleBindings/Types/SimpleEnumType.g.h" #include "ModuleBindings/Types/TableHoldsTableType.g.h" diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Public/Tests/UmbreallaHeaderaTables.h b/sdks/unreal/tests/TestClient/Source/TestClient/Public/Tests/UmbreallaHeaderaTables.h index d901195b5f3..f79650429f5 100644 --- a/sdks/unreal/tests/TestClient/Source/TestClient/Public/Tests/UmbreallaHeaderaTables.h +++ b/sdks/unreal/tests/TestClient/Source/TestClient/Public/Tests/UmbreallaHeaderaTables.h @@ -53,6 +53,12 @@ #include "ModuleBindings/Tables/PkU32TwoTable.g.h" #include "ModuleBindings/Tables/PkU64Table.g.h" #include "ModuleBindings/Tables/PkU8Table.g.h" +#include "ModuleBindings/Tables/ResultEveryPrimitiveStructStringTable.g.h" +#include "ModuleBindings/Tables/ResultI32StringTable.g.h" +#include "ModuleBindings/Tables/ResultIdentityStringTable.g.h" +#include "ModuleBindings/Tables/ResultSimpleEnumI32Table.g.h" +#include "ModuleBindings/Tables/ResultStringI32Table.g.h" +#include "ModuleBindings/Tables/ResultVecI32StringTable.g.h" #include "ModuleBindings/Tables/ScheduledTableTable.g.h" #include "ModuleBindings/Tables/TableHoldsTableTable.g.h" #include "ModuleBindings/Tables/UniqueBoolTable.g.h" diff --git a/sdks/unreal/tests/TestProcClient/Source/TestProcClient/Public/ModuleBindings/SpacetimeDBClient.g.h b/sdks/unreal/tests/TestProcClient/Source/TestProcClient/Public/ModuleBindings/SpacetimeDBClient.g.h index 5a6d1f4e62b..7e8014a598e 100644 --- a/sdks/unreal/tests/TestProcClient/Source/TestProcClient/Public/ModuleBindings/SpacetimeDBClient.g.h +++ b/sdks/unreal/tests/TestProcClient/Source/TestProcClient/Public/ModuleBindings/SpacetimeDBClient.g.h @@ -1,7 +1,7 @@ // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE // WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. -// This was generated using spacetimedb cli version 1.8.0 (commit ce4a0dc173e8e177348af6854f20525a359c59a2). +// This was generated using spacetimedb cli version 1.10.0 (commit 4324cd74366922cb2df02fffaf7bc268c7044b1f). #pragma once #include "CoreMinimal.h" diff --git a/sdks/unreal/tests/TestProcClient/Source/TestProcClient/Public/ModuleBindings/Types/ReturnEnumType.g.h b/sdks/unreal/tests/TestProcClient/Source/TestProcClient/Public/ModuleBindings/Types/ReturnEnumType.g.h index a0235284c48..14b4b797c33 100644 --- a/sdks/unreal/tests/TestProcClient/Source/TestProcClient/Public/ModuleBindings/Types/ReturnEnumType.g.h +++ b/sdks/unreal/tests/TestProcClient/Source/TestProcClient/Public/ModuleBindings/Types/ReturnEnumType.g.h @@ -22,7 +22,7 @@ struct TESTPROCCLIENT_API FReturnEnumType public: FReturnEnumType() = default; - TVariant MessageData; + TVariant MessageData; UPROPERTY(BlueprintReadOnly) EReturnEnumTag Tag = static_cast(0); diff --git a/sdks/unreal/tests/test.rs b/sdks/unreal/tests/test.rs index 85ba36c83c8..dc324d2ad9d 100644 --- a/sdks/unreal/tests/test.rs +++ b/sdks/unreal/tests/test.rs @@ -291,3 +291,9 @@ fn unreal_indexed_simple_enum() { fn unreal_overlapping_subscriptions() { make_test("OverlappingSubscriptionsTest").run(); } + +#[test] +#[serial(Group6)] +fn unreal_insert_result_okay() { + make_test("InsertResultOkTest").run(); +} From 8b2f5e0dd904131c39a7b78d0163cd79c49557ff Mon Sep 17 00:00:00 2001 From: Jason Larabie Date: Fri, 5 Dec 2025 19:12:04 -0800 Subject: [PATCH 3/3] Tools being "helpful" by including things that aren't necessary --- crates/codegen/src/unrealcpp.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/codegen/src/unrealcpp.rs b/crates/codegen/src/unrealcpp.rs index 0ddab050f5e..4701488d21c 100644 --- a/crates/codegen/src/unrealcpp.rs +++ b/crates/codegen/src/unrealcpp.rs @@ -20,7 +20,6 @@ use std::collections::HashSet; use std::fmt::{self}; use std::ops::Deref; use std::path::Path; -use std::result; pub struct UnrealCpp<'opts> { pub module_name: &'opts str,